c++11—type_traits
类型萃取即对类型进行操作,例如获取类型的名称、去除类型的修饰符、增加“类型”的修饰符。c++11
的头文件#include <type_traits>
中提供了很多的类模板帮助我们对类型进行萃取。下面对一些常见的类型萃取进行说明。
常量的萃取
integral_constant
用于获取某个类型静态常量,声明如下:
template<class T, T v> |
这里额外提供了两个bool
的常量值std::true_type
和std::false_type
,标准库中的声明如下,这两个常量对于其他萃取器的实现有非常大作用:
typedef integral_constant<bool, true> true_type; |
类型种类的萃取
这种萃取能帮助我们判断一个类型是否是整形还是浮点型等。
is_integral
判断一个类型是否是整形,声明如下:
template<class T> |
简单的使用:
// std::is_integral<T>::value |
可以利用模板的偏特化实现一个简单版本:
|
为了方便使用,c++17
新增了对应的变量模板,拥有成员变量value的萃取类一般都提供了变量模板:
template<class T> |
…
下面是一些主要的类型种类萃取。
类模板 | 用途 |
---|---|
is_void |
检查类型是否是void |
is_array |
检查类型是否是array |
is_enum |
检查类型是否是enum |
is_union |
检查类型是否是union |
is_class |
检查类型是否是class |
is_pointer |
检查类型是否是指针类型 |
is_function |
检查类型是否是函数类型 |
is_lvalue_reference |
检查类型是否是左值引用 |
is_rvalue_reference |
检查类型是否是右值引用 |
is_member_object_pointer |
检查类型是否是指向非静态成员对象的指针 |
is_member_function_pointer |
检查类型是否是指向非静态成员函数的指针 |
类型属性的萃取
这种萃取能帮助我们判断一个类型是否拥有某些属性。
is_const
判断一个类型是否是const
限定的,声明如下:
template<class T> |
可以利用偏特化实现,标准库中的实现:
template<typename> |
…
类模板 | 用途 |
---|---|
is_volatile |
检查类型是否是volatile 限定的 |
is_abstract |
检查是否是抽象类类型 |
… | … |
某类属性增删的萃取
remove_const
去除类型的const属性,声明如下:
template< class T > |
标准库中的实现:
template<typename _Tp> |
在c++11
中的使用:
std::remove_const<T>::type; |
为了简化使用,在c++14
中提供了对应的别名模板,拥有type类型的萃取类一般都提供别名模板:
template< class T > |
相应的remove_volatile
和remove_cv
与之类似。
add_volatile
给类型增加volatile属性,声明如下:
template< class T > |
标准库中的实现:
template<typename _Tp> |
相应的add_const
和add_cv
与之类似。
…
类模板 | 用途 |
---|---|
remove_const |
去除类型的const 属性 |
remove_volatile |
去除类型的volatile 属性 |
remove_cv |
去除类型的const 和volatile 属性 |
remove_reference |
去除给定类型的引用,包括左值引用和右值引用 |
add_const |
给类型增加const 属性 |
add_volatile |
给类型增加volatile 属性 |
add_cv |
给类型增加const 和volatile 属性 |
remove_pointer |
去除类型的指针属性 |
add_pointer |
给一个类型增加指针的属性 |
… | … |
类型间关系的萃取
is_same
判断两个类型是否相同,声明如下:
template<class T, class U> |
标准库中的实现:
template<typename, typename> |
简单的使用:
// c++11 |
is_base_of
检查一个类型是否派生于其他类型,声明如下:
template<class Base, class Derived> |
is_convertible
检查一个类型是否能转换成另一个类型,声明如下:
template<class From, class To> |
简单的使用:
// c++14 |
is_invocable(c++17)
检查给定的函数、函数对象、函数指针或成员函数指针是否可以用给定的参数类型进行调用,声明如下:
template<class Fn, class... ArgTypes> |
…
类模板 | 用途 |
---|---|
is_same |
检查两个类型是否相同 |
is_base_of |
检查一个类型是否派生于其他类型 |
is_convertible |
检查一个类型是否能转换成其他类型 |
is_invocable |
检查给定的函数、函数对象、函数指针或成员函数指针是否可以用给定的参数类型进行调用 |
… | … |
支持某类操作的萃取
is_default_constructible
检查类型是否拥有默认构造函数,声明如下:
template< class T > |
简单的使用:
// c++11 |
可以利用SFINAE
特性排除偏特化的方式来实现,可能的实现方式:
|
…
类模板 | 用途 |
---|---|
is_default_constructible |
检查类型是否拥有默认构造函数 |
is_constructible |
检查类型是否拥有构造函数 |
is_copy_constructible |
检查类型是否拥有拷贝构造函数 |
has_virtual_destructor |
检查类型是否拥有虚析构函数 |
… | … |
各种变化的萃取
decay
能去除const
、volatile
的修饰,去除引用,将数组类型转换成指针,将函数类型转换成函数指针类型。声明如下:
template<class T> |
简单的使用:
// c++11 |
decay
可能的简单实现如下:
|
void_t
能够检测出应用SFINAE
特性时出现的非法类型。传入到std::void_t
中的类型必须是一个有效的类型。定义如下:
template< class... > |
用来探测类变量的实例:
|
enable_if
有条件的从重载解析中删除函数重载和模板特化,声明如下:
template<bool B, class T = void> |
只有当判断条件为true
时,enable_if<...>::type
才会存在,type
类型和T
保持一致,默认是void
。
简单的使用:
|
conditional
条件选择萃取类型,声明如下:
template<bool B, class T, class F> |
如果B
为true
,则conditional<...>::type
的类型是T
,否则就是F
。
简单的使用:
|
invoke_result
获取可调用对象输入一组参数后返回结果的类型,声明如下:
template<class F, class... ArgTypes> |
有一个类模板result_of
也是差不多的效果,不过在c++17
就不推荐使用了。在c++20
的时候又增加了一个函数模板invoke
对类模板invoke_result
进行简单的封装,声明如下:
template<class F, class... Args> |
参考
- https://en.cppreference.com/w/cpp/header/type_traits
- 《c++ template 第二版》