给定任何类型 T 时手动区分类型

使用 std::enable_if 实现 SFINAE 时 ,访问辅助模板通常很有用,可以确定给定类型 T 是否与一组条件匹配。

为了帮助我们,该标准已经提供了两种类型的 truefalse,分别是 std::true_typestd::false_type

以下示例显示如何检测类型 T 是否为指针,is_pointer 模板模仿标准 std::is_pointer 帮助程序的行为:

template <typename T>
struct is_pointer_: std::false_type {};

template <typename T>
struct is_pointer_<T*>: std::true_type {};

template <typename T>
struct is_pointer: is_pointer_<typename std::remove_cv<T>::type> { }

上面的代码有三个步骤(有时你只需要两个):

  1. is_pointer_ 的第一个声明是默认情况,并继承自 std::false_type。在默认的情况下,应始终从 std::false_type 继承,因为它是类似于一个“false 条件”。

  2. 第二个声明专门用于指示 T*is_pointer_ 模板,而不关心 T 究竟是什么。此版本继承自 std::true_type

  3. 第三个声明(真正的声明)只是从 T 删除任何不必要的信息(在这种情况下我们删除了 constvolatile 限定符),然后回退到前两个声明中的一个。

由于 is_pointer<T> 是一个类,要访问它的值,你需要:

  • 使用::value,例如 is_pointer<int>::value - valuebool 的静态类成员,继承自 std::true_typestd::false_type;
  • 构造一个这种类型的对象,例如 is_pointer<int>{} - 这是因为 std::is_pointerstd::true_typestd::false_type(有 constexpr 构造函数)继承了它的默认构造函数,std::true_typestd::false_type 都有 constexpr 转换运算符到 bool

提供帮助程序帮助程序模板是一个很好的习惯,可以让你直接访问该值:

template <typename T>
constexpr bool is_pointer_v = is_pointer<T>::value;

Version >= C++ 17

在 C++ 17 及更高版本中,大多数帮助器模板已经提供了 _v 版本,例如:

template< class T > constexpr bool is_pointer_v = is_pointer<T>::value;
template< class T > constexpr bool is_reference_v = is_reference<T>::value;