type trait是一系列模板,描述了类型的特征,定义在<type_traits>。
类型判断
trait | 作用 |
---|---|
is_void | 是否void |
is_integral | 整数类型(包括bool、char、char16_t、char32_t、wchar_t) |
is_floating_point | 浮点数类型 |
is_arithmetic | 整数(包括bool、char、char16_t、char32_t、wchar_t)或浮点数 |
is_signed | 带符号 |
is_unsigned | 不带符号 |
is_const | 带const限定符 |
is_volatile | 带volatile限定符 |
is_array | 普通数组 |
is_enum | 枚举 |
is_union | 联合 |
is_class | 类类型或结构体类型 |
is_function | 函数类型 |
is_reference | 引用 |
is_lvalue_reference | 左值引用 |
is_rvalue_reference | 右值引用 |
is_pointer | 指针类型,包括函数指针,不包括指向nonstatic成员的指针 |
is_member_pointer | 指向nonstatic成员的指针 |
is_member_object_pointer | 指向nonstatic数据成员的指针 |
is_member_funciton_pointer | 指向nonstatic成员函数的指针 |
is_fundamental | void、整数类型(包括bool、char、char16_t、char32_t、wchar_t)、浮点数、nullptr_t |
is_scalar | 整数类型、浮点数、枚举、pointer、member pointer、nullptr_t |
is_object | 任何类型,除了void、funciton和reference |
is_compound | 普通数组 、枚举、联合、class、function、reference、pointer |
is_trivial | Scalar、trivially copyable class 或那些类型构成的array |
is_trivially_copyable | Scalar、trivially copyable class 或那些类型构成的array |
is_standard_layout | Scalar、standard layout class 或那些类型构成的array |
is_pod | |
is_literal_type | Scalar、reference、class或那些类型构成的数组 |
class类型特征判断
trait | 作用 |
---|---|
is_empty | class不带任何成员、virtual 成员函数或 virtual base data |
is_polymorphic | class带有一个 virtual 成员函数 |
is_abstract | 抽象类 |
has_virtual_destructor | 带有虚析构函数 |
is_default_constructible | 能完成默认构造 |
is_copy_constructible | 能完成复制构造 |
is_move_constructible | 能完成移动构造 |
is_copy_assignable | 能完成复制语义赋值 |
is_move_assignable | 能完成移动语义赋值 |
is_destructible | 带可被调用析构函数(不可以是deleted、protected、private) |
is_trivially_default_constructible | 能完成trivial 默认构造 |
is_trivially_copy_constructible | 能完成 trivial 复制构造 |
is_trivially_move_constructible | 能完成trivial 移动构造 |
is_trivially_copy_assignable | 能完成trivial 赋值 |
is_trivially_move_assignable | 能完成trivial 移动语义赋值 |
is_trivially_destructible | 带有可被调用的trivial 析构函数 |
is_nothrow_default_constructible | 能完成不抛出异常的默认构造 |
is_nothrow_copy_constructible | 能完成不抛出异常的复制构造 |
is_nothrow_move_constructible | 能完成不抛出异常的移动构造 |
is_nothrow_copy_assignable | 能完成不抛出异常的赋值 |
is_nothrow_move_assignable | 能完成不抛出异常的移动语义赋值 |
is_nothrow_destructible | 带可被调用不抛出异常的析构函数 |
判断类型的关系
trait | 作用 |
---|---|
is_same<T1,T2> | T1和T2是不是相同类型 |
is_base_of<T,D> | T是不是D的基类 |
is_convertible<T1,T2> | T1是否可以转换为T2 |
is_constructible<T,Ags…> | T是否可以用Args…中的类型构造 |
is_trivially_constructible<T,Args…> | T是否可以用Args中的类型trivially构造 |
is_nothorw_constructible<T,Arts…> | T是否可以用Args中类型构造且不抛出异常 |
is_assignable<T1,T2> | 是否可用T2对T1进行赋值 |
is_nothrow_assignable<T1,T2> | 是否可用T2对T1进行赋值且不抛出异常 |
uses_allocator<T,Alloc> | Alloc是否可转换为T::allocator_type |
值得注意,上述的trait中 T 是被视作右值的。对于基础内置数据类型,使用内置赋值操作符是不能对右值赋值的,所以类似 is_assignable<int,int>::value的结果总是false。但是,对于类类型,赋值操作是使用其成员函数,而且类类型的右值可以调用成员函数,所以 is_assignable<string,string>::value 结果是true。
改变类型
trait | 作用 |
---|---|
remove_const | 移除const |
remove_volatile | 移除 volatile |
remove_cv | 移除 const 和 volatile |
add_const | 添加const |
add_volatile | 添加 volatile |
add_cv | 添加 const 和 volatile |
make_signed | 转为对应带符号 nonreference 类型 |
make_unsigned | 转为对应的不带符号 nonreference 类型 |
remove_reference | 移除引用 |
add_lvalue_reference | 添加左值引用(右值变为左值) |
add_rvalue_reference | 添加右值引用(左值保持左值) |
remove_pointer | 转为指针指向的类型(不是指针返回原类型) |
add_pointer | 转为指针类型,指向对应的nonreference类型 |
其他type trait
trait | 作用 |
---|---|
rank | 获取数组类型的维度 |
extent<T,I=0> | 维度 I 的宽度 |
remove_extent | 获取数组的元素类型,如果 T 不是数组则获得 T |
remove_all_extents | 获取多维数组的元素类型,如果 T 不是多维数组则获得 T |
underlying_type | 枚举类型的底层类型 |
decay | 将 T 转换为对应的实值类型 |
enable_if<B, T=void> | B 为 true 时返回 T |
condition<B, T, F> | B 为 true 时 返回 T, 否则返回 F |
common_type<T1,…> | 返回所有传入类型的共通类型 |
result_of<F, ArgTypes> | 返回调用 F 的返回类型, ArgTypes 为 F 的实参类型 |
alignment_of | 等价于 alignof(T) |
aligned_storage | |
aligned_storage<Len, Align> | |
aligned_union<Len, Types…> |
common_type<> trait 会返回所有传入类型的共通类型,所谓的共通类型可以理解为,其它类型都可以通过隐式类型转换 转换为它。对于内置数值类型,隐式类型转换总是从低精度到高精度,所以 common_type<> 应用于内置数值类型时,总是返回高精度的类型。
查找共通类型的功能实际是三目运算符 :? 提供,它的返回值带有类型,就是共通类型。如果三目运算符的操作数不存在共通类型,就会提示编译错误 “操作数类型不兼容”。因为 :? 日常使用通常应用于相同类型,所以会忽略了 :? 这一特性:
double d = 9.0;
std::cout << typeid(true ? 1 : d).name() << std::endl; // 输出 double
std::cout << typeid(true ? 1 : "d").name() << std::endl; // error
common_type<>的实现类似:
template <typename T1, typename T2>
struct common_type<T1, T2>
{
typedef decltype(true ? declval<T1>() :: declval<T2>()) type;
}
reference wrapper(外覆器)
reference wrapper的一个用途是给函数模板的参数赋予引用属性。对于类型 T,ref()把类型转换为 T&,cref() 把类型转换为 const T&。这允许了函数模板不用提供针对引用参数的的特化版本:
template <typename T>
void foo(T val);
int x;
foo(ref(x));
foo(cref(x));
标准库中的 make_pair<>、make_tuple()、Binder 和 Thread 都使用了这特性。
function type wrapper
function<>可以把C++的可调用对象,如函数、函数对象、lambda表达式等封装:
void sayhello()
{
std::cout << "hello" << std::endl;
}
function<void()> func(sayhello);
func();