开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情
背景
定义在<type_traits>中,用于判断一个类型是否是如下的混合类型:
- is_reference:是否是引用类型
- is_arithmetic:是否是算术类型
- is_fundamental:是否是基础类型
- is_object:是否是对象
- is_member_pointer:是否是成员指针
- is_scalar:是否是数据类型,可进行计算
- is_compound:是否是复合类型
代码实现
gcc官网:gcc.gnu.org/
gcc代码下载:mirrors.tuna.tsinghua.edu.cn/help/gcc.gi…
gcc版本代码:gcc-7.5.0(branch分支)
文件位置:gcc/libstdc++-v3/include/std/type_traits
注意:以下的代码实现省略了一些宏定义部分,实际的代码还是参考gcc源码,这里仅用作相关原理分析。
实现分析
is_reference
判断_Tp是否是左值引用或右值引用,借助__or_得到最终的结果。
/// is_reference
template<typename _Tp>
struct is_reference
: public __or_<is_lvalue_reference<_Tp>,
is_rvalue_reference<_Tp>>::type
{ };
is_arithmetic
判断_Tp是否是int类型或者浮点类型。
/// is_arithmetic
template<typename _Tp>
struct is_arithmetic
: public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type
{ };
is_fundamental
判断基础类型:算术类型,void类型,null_pointer类型。
/// is_fundamental
template<typename _Tp>
struct is_fundamental
: public __or_<is_arithmetic<_Tp>, is_void<_Tp>,
is_null_pointer<_Tp>>::type
{ };
is_object
类型_Tp不是函数、引用、void之一,被认为是对象类型。
/// is_object
template<typename _Tp>
struct is_object
: public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
is_void<_Tp>>>::type
{ };
is_member_pointer
成员指针主要是通过对指针_Tp _Cp::*的识别,默认继承false_type,注意在最开始的位置我们需要调用remove_cv去除const和volatile属性。
template<typename _Tp>
struct __is_member_pointer_helper
: public false_type { };
template<typename _Tp, typename _Cp>
struct __is_member_pointer_helper<_Tp _Cp::*>
: public true_type { };
/// is_member_pointer
template<typename _Tp>
struct is_member_pointer
: public __is_member_pointer_helper<typename remove_cv<_Tp>::type>::type
{ };
is_scalar
数据类型包括算术类型,枚举类型,以及所有的指针类型(普通指针,成员指针,空指针)。
/// is_scalar
template<typename _Tp>
struct is_scalar
: public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>,
is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
{ };
is_compound
复合类型:不是基础类型的都是复合类型
/// is_compound
template<typename _Tp>
struct is_compound
: public integral_constant<bool, !is_fundamental<_Tp>::value> { };
使用案例
#include <iostream>
#include <type_traits>
class A{};
enum E{e};
int main(){
#define LINE(x) std::cout << #x " ?: " << x << "\n"
std::cout << std::boolalpha;
std::cout << "------is_reference------\n";
LINE(std::is_reference<int&>::value);
LINE(std::is_reference<int&&>::value);
LINE(std::is_reference<int*&>::value);
LINE(std::is_reference<int*&&>::value);
std::cout << "------is_arithmetic------\n";
LINE(std::is_arithmetic<int>::value);
LINE(std::is_arithmetic<bool>::value);
LINE(std::is_arithmetic<char>::value);
LINE(std::is_arithmetic<char*>::value);
LINE(std::is_arithmetic<char&>::value);
std::cout << "------is_fundamental------\n";
LINE(std::is_fundamental<int>::value);
LINE(std::is_fundamental<float>::value);
LINE(std::is_fundamental<int*>::value);
LINE(std::is_fundamental<float&>::value);
std::cout << "------is_object------\n";
LINE(std::is_object<int>::value);
LINE(std::is_object<float>::value);
LINE(std::is_object<A>::value);
LINE(std::is_object<int*>::value);
LINE(std::is_object<float&>::value);
std::cout << "------is_member_pointer------\n";
LINE(std::is_member_pointer<int(A::*)>::value);
LINE(std::is_member_pointer<int*>::value);
std::cout << "------is_scalar------\n";
LINE(std::is_scalar<int>::value);
LINE(std::is_scalar<decltype(E::e)>::value);
LINE(std::is_scalar<int*>::value);
LINE(std::is_scalar<int(A::*)>::value);
std::cout << "------is_compound------\n";
LINE(std::is_compound<int>::value);
LINE(std::is_compound<A>::value);
LINE(std::is_compound<E>::value);
return 0;
}
基本上就是对前面类型的总结和组合,测试结果如下:
总结
- is_reference:是否是引用类型
- is_arithmetic:是否是算术类型
- is_fundamental:是否是基础类型
- is_object:是否是对象
- is_member_pointer:是否是成员指针
- is_scalar:是否是数据类型,可进行计算
- is_compound:是否是复合类型