1、概念
C++ 中的 type traits 是一种模板元编程技术,用于在编译期间判断、查询类型的属性。Type traits 可以帮助程序员在编译时进行类型判断,而不是在运行时判断,避免了程序中的不必要开销,并且可以提供更好的类型安全性。
2、用途
Type traits 提供了许多模板类和变量,用于查询类型的属性和特征,包括以下几个方面:
- 类型类别:判断类型是否是某个类别,例如 std::is_pointer 用于检查类型 T 是否为指针类型。
- 空间特性:判断类型的内存布局,比如是否为标准布局类型、是否为平凡类型等。
- 转换能力:判断类型是否能隐式转换为另一种类型,例如 std::is_convertible<A,B> 用于判断类型 A 是否能够隐式转换为类型 B。
- 类型转换:去除或者添加类型修饰符const、volatile、&、*。例如 std::decay 用于去掉 T 所有修饰符:引用、 const、volatile。
- 获取类型之间的关系:common_type<T1, T2>用于计算类型 T1 和类型T2 的公共类型;is_base_of<Base, Derived>用于判断类型 Base 是否是类型 Derived 的基类。
- 条件元编程:conditional<C, T1, T2>用于根据类型 C 是否为真,选择返回类型 T1 或 T2;例如 std::enable_if<B, T> 用于根据条件 B 启用或禁用模板函数或类。
3、例子
以下是一个使用Type Traits的示例:
#include <iostream>
#include <type_traits>template <typename T>
void printIfIntegral(const T& val)
{if (std::is_integral<T>::value) {std::cout << "整数类型" << std::endl;}else {std::cout << "非整数类型" << std::endl;}
}int main()
{printIfIntegral(10);//输出:整数类型printIfIntegral(9.8);//输出:非整数类型printIfIntegral("hello world");//输出:非整数类型return 0;
}
在这个例子中,我们定义了一个 printIfIntegral 函数,该函数接受一个参数 val,并使用 std::is_integral 来判断该参数是否为整数类型。
4、原理
下面举几个例子简单介绍一下部分type traits的实现原理。
4.1、is_pointer
以下是std::is_pointer的简单实现:
template<typename T>
struct is_pointer {static const bool value = false;
};template<typename T>
struct is_pointer<T*> {static const bool value = true;
};
这个实现通过对不同类型进行特化来判断它们是否为指针类型。如果一个类型与T*匹配,那么value成员变量就被置为true。否则,value保持为默认值false。
4.2、enable_if
std::enable_if是C++标准库中的一个类型特性,当第一个模板参数为false的时候,enable_if<>::type不表示任何类型。以下是std::enable_if的简单实现:
template<bool B, typename T = void>
struct enable_if {};template<typename T>
struct enable_if<true, T> {using type = T;
};
这个实现定义了一个类模板enable_if,它有两个参数:bool B表示条件是否满足,typename T表示返回的类型(默认为void)。如果B为false,则不会定义type成员类型;否则,会定义type成员类型为T。