关于实施标准::add_pointer的问题

A question regarding the implementation of std::add_pointer

本文关键字:pointer 问题 add 于实施 标准      更新时间:2023-10-16

From std::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 是引用类型,则提供成员类型定义类型 是指向引用类型的指针。

否则,如果 T 命名对象类型,则不是 cv- 或参考合格,或(可能符合 CV 标准(空隙类型,提供 成员类型定义类型,即类型 T*。

否则(如果 T 是符合 cv 或 ref 条件的函数类型(,则提供 成员类型定义类型,即类型 T。

在上面的(可能的(实现代码中,显然struct add_pointer派生自detail::try_add_pointer<T>(0)返回的类型。

detail::try_add_pointer<T>接受参数的重载返回的类型派生int将成员typedef type解析为上述三种可能性之一的逻辑是什么?具体来说,这如何解决Tcv-ref-限定函数类型的可能性?

关键在于了解detail::try_add_pointer<T>(0)的重载解析是如何工作的。将T代入detail::try_add_pointer意味着生成始终包含至少一个成员的重载集(变量参数重载(。

在过载解决(SFINAE(期间是否丢弃int的过载取决于将T替换为typename std::remove_reference<T>::type*的成功。当替换成功时,存在重载,并且重载分辨率与 0 的匹配度更好(省略号是与任何其他转换序列相比最差的匹配(。无论哪种方式,无论在重载解析中选取哪个重载,decltype(detail::try_add_pointer<T>(0))都将解析为具有嵌套::type成员的内容。

因此,让我们逐案分析:

  1. "如果 T 是引用类型" - 让我们将其标记为T = T2&.那么std::remove_reference<T>::typeT2了.我们可以形成引用的类型也是我们可以形成指针的类型。所以std::remove_reference<T>::type*格式正确(它是T2*(,并且存在第一个重载。它在过载分辨率中被拾取。其返回类型的嵌套::typeT2*

  2. "否则,如果 T 命名一个对象类型,一个不符合 cv 或 ref 限定的函数类型,或者一个(可能符合 cv 限定的(void 类型" - 在这种情况下,std::remove_reference<T>::type只是T。我们可以形成指向上一个列表中的任何类型的指针,因此std::remove_reference<T>::type*再次形成良好格式(并且T*(。第一个重载再次存在,并以重载解析方式拾取。其返回类型的嵌套::typeT*

  3. "否则(如果 T 是符合 cv 或 ref 条件的函数类型(" - 有趣的位。这说明了像void (int) const&.这里又std::remove_reference<T>::typeT.但是我们不允许形成指向T的指针,基本语言禁止这样做。因此std::remove_reference<T>::type*格式不正确,对于此重载解析,将忽略第一个重载。只剩下第二个重载,它是重载分辨率拾取的重载。其返回类型的嵌套::typeT

继承只是使用type_identity包装器(已经需要形成有效的返回类型(以最小的工作量定义特征的一种方式。 重载技巧依赖于以下事实:std::remove_reference是非引用类型的标识,并且(处理了引用(std::add_pointer<T>T*,除非根本没有此类类型。 在这种情况下,SFINAE 会消除int过载并选择...(仅产生T(。