From std::add_pointer https://en.cppreference.com/w/cpp/types/add_pointer
可能的实施
namespace detail {
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;
} // namespace detail
template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};
上述(可能的)实现的描述如下:
如果 T 是引用类型,则提供成员 typedef 类型,其中
是指向所引用类型的指针。
否则,如果 T 命名一个对象类型,则该函数类型不是 cv-
或 ref 限定的,或(可能是 cv 限定的)void 类型,提供
成员 typedef type 是 T* 类型。
否则(如果 T 是 cv 或 ref 限定的函数类型),则提供
成员 typedef type 是类型 T。
在上面的(可能的)实现代码中,显然struct add_pointer
派生自返回的类型detail::try_add_pointer<T>(0)
.
从重载返回的类型派生背后的逻辑是什么detail::try_add_pointer<T>
taking int
争论,解决成员typedef type
上述三种可能性之一?具体来说,如果T
is a cv-
or ref-
合格的函数类型?
关键是理解如何重载解析detail::try_add_pointer<T>(0)
作品。替代T
into detail::try_add_pointer
旨在生成一个始终包含至少一个成员的重载集(变量参数重载)。
是否过载int
在重载决策期间被丢弃(SFINAE https://en.cppreference.com/w/cpp/language/sfinae)由替换成功决定T
into typename std::remove_reference<T>::type*
。当替换成功时,重载存在,并且在重载解析中是 0 的更好匹配(与任何其他转换序列相比,省略号是最差的可能匹配)。无论哪种方式,无论在重载决策中选择哪个重载,decltype(detail::try_add_pointer<T>(0))
将解析为具有嵌套的内容::type
member.
那么我们就来具体案例分析一下:
“如果 T 是引用类型” - 让我们标记一下T = T2&
. Then std::remove_reference<T>::type
is T2
。我们可以形成引用的类型也是我们可以形成指针的类型。所以std::remove_reference<T>::type*
是格式良好的(它是T2*
),并且存在第一个过载。它是在过载解析中拾取的。嵌套的::type
其返回类型是T2*
.
“否则,如果 T 命名一个对象类型、一个非 cv 或 ref 限定的函数类型,或者一个(可能是 cv 限定的)void 类型” - 在这种情况下std::remove_reference<T>::type
简直就是T
。我们可以形成一个指向前面列表中任何类型的指针,等等std::remove_reference<T>::type*
再次形成良好(并且它是T*
)。第一个重载再次存在并在重载决策中被拾取。嵌套的::type
其返回类型是T*
.
“否则(如果 T 是 cv 或 ref 限定的函数类型)” - 有趣的一点。这谈到了像这样的类型void (int) const&
。又是在这里std::remove_reference<T>::type
is T
。但我们不允许形成一个指向T
,基本语言禁止它。所以std::remove_reference<T>::type*
格式不正确,对于此重载决策,第一个重载将被忽略。只剩下第二个重载,这是重载解析所拾取的重载。嵌套的::type
其返回类型是T
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)