C++11中头文件type_traits介绍

C++11中的头文件type_traits定义了一系列模板类,在编译期获得某一参数、某一变量、某一个类等等类型信息,主要做静态检查

此头文件包含三部分:

(1).Helper类:帮助创建编译时常量的标准模板类。介绍见以下测试代码:

template 
struct factorial : std::integral_constant::value> {};

template <>
struct factorial<0> : std::integral_constant {};

constexpr unsigned test_integral_constant() noexcept { return factorial<5>::value; }
static_assert(test_integral_constant() == 120, "value should be 120");

// reference: https://stackoverflow.com/questions/58694521/what-is-stdfalse-type-or-stdtrue-type
struct true_type {
	static constexpr bool value = true;
	constexpr operator bool() const noexcept { return value; }
	// ...
};

struct false_type {
	static constexpr bool value = false;
	constexpr operator bool() const noexcept { return value; }
	// ...
};

int test_type_traits_helper_classes()
{
	// std::integral_constant: 编译时将常量作为类型,一般用做trait type的基类
	static_assert(factorial<5>::value == 120, "value should be 120");
	fprintf(stdout, "result: %u\n", factorial<5>::value); // constexpr(no calculations on runtime)

	// std::true_type: ==> std::integral_constant, 实例化integral_constant用以表示布尔值true
	static constexpr bool value1 = true;
	static_assert(std::integral_constant::value == true, "value should be true");

	// std::false_type: ==> std::integral_constant, 实例化integral_constant用以表示布尔值false
	static constexpr bool value2 = false;
	static_assert(std::integral_constant::value == false, "value should be false");

	return 0;
}

(2).类型特征(Type traits):以编译时常量值的形式获取类型特征(characteristics of types)的模板类。介绍见以下测试代码:

int func(int i) { return i; }
class A { public: void func() {} };
struct B { int func(int a) { return a; } };
union C { int i; float f; };
enum class D { x, y, z };
struct F { int a; };
struct G { virtual void func() = 0; };
struct H { virtual void func() {} };
struct I : G { void func() override {} };
struct J { ~J() {} };
struct K { int x; K(const K& k) : x(k.x){}; };
struct L { virtual ~L() {} };
struct M { M& operator=(M&&) = delete; };
struct N { N& operator=(const A&) { return *this; } };
struct P { P(int) {} };
struct Q { ~Q() = delete; };
struct R : B { };
struct S {};

int test_type_traits_type_traits()
{
	// 1.Primary type categories
	// std::is_array: T是不是数组类型,注意:此函数不会将数组类模板的实例化视为数组类型
	static_assert(std::is_array::value == false, "");
	static_assert(std::is_array::value == true, "");
	static_assert(std::is_array>::value == false, "");

	// std::is_class: T是不是类类型
	static_assert(std::is_class::value == true, "");
	static_assert(std::is_class::value == true, "");
	static_assert(std::is_class::value == false, "");

	// std::is_enum: T是不是枚举类型
	static_assert(std::is_enum::value == true, "");
	static_assert(std::is_enum::value == false, "");

	// std::is_floating_point: T是不是浮点类型
	static_assert(std::is_floating_point::value == true, "");
	static_assert(std::is_floating_point::value == false, "");
	static_assert(std::is_floating_point::value == true, "");

	// std::is_function: T是不是函数类型
	static_assert(std::is_function::value == true, "");
	static_assert(std::is_function::value == true, "");

	// std::is_integral: T是不是整数类型
	static_assert(std::is_integral::value == true, "");
	static_assert(std::is_integral::value == true, "");
	static_assert(std::is_integral::value == true, "");

	// std::is_lvalue_reference: T是不是左值引用类型
	static_assert(std::is_lvalue_reference::value == true, "");
	static_assert(std::is_lvalue_reference::value == false, "");

	// std::is_rvalue_reference: T是不是右值引用类型
	static_assert(std::is_rvalue_reference::value == false, "");
	static_assert(std::is_rvalue_reference::value == true, "");

	// std::is_member_function_pointer: T是不是非静态成员函数指针类型
	void(A::*pt)() = &A::func;
	static_assert(std::is_member_function_pointer::value == true, "");
	static_assert(std::is_member_function_pointer::value == true, "");
	static_assert(std::is_member_function_pointer::value == false, "");

	// std::is_member_object_pointer: T是不是非静态成员数据指针类型
	int F::* pt2 = &F::a;
	static_assert(std::is_member_object_pointer::value == true, "");
	static_assert(std::is_member_object_pointer::value == true, "");

	// std::is_pointer: T是不是指针类型
	static_assert(std::is_pointer::value == true, "");
	static_assert(std::is_pointer::value == true, "");
	static_assert(std::is_pointer::value == true, "");

	//  std::is_union: T是不是联合体类型
	static_assert(std::is_union::value == true, "");
	static_assert(std::is_union::value == false, "");

	// std::is_void: T是不是void类型
	static_assert(std::is_void::value == true, "");
	static_assert(std::is_void::value == false, "");

	// 2.Composite type categories: 复合类型
	// std::is_arithmetic: T是不是算术类型
	static_assert(std::is_arithmetic::value == true, "");
	static_assert(std::is_arithmetic::value == false, "");

	// std::is_compound: T是不是复合类型,即不是基础类型
	static_assert(std::is_compound::value == false, "");
	static_assert(std::is_compound::value == true, "");
	static_assert(std::is_compound::value == true, "");

	// std::is_fundamental: T是不是基础类型
	static_assert(std::is_fundamental::value == true, "");
	static_assert(std::is_fundamental::value == false, "");
	static_assert(std::is_fundamental::value == true, "");

	// std::is_member_pointer: T是不是非静态成员指针类型
	int F::* pt3 = &F::a;
	static_assert(std::is_member_pointer::value == true, "");
	static_assert(std::is_member_pointer::value == true, "");
	static_assert(std::is_member_pointer::value == true, "");

	// std::is_object: T是不是对象类型,除函数、引用、void之外的所有类型
	static_assert(std::is_object::value == true, "");
	static_assert(std::is_object::value == false, "");
	static_assert(std::is_object::value == false, "");
	static_assert(std::is_object::value == true, "");

	// std::is_reference: T是不是引用类型,左值引用或右值引用
	static_assert(std::is_reference::value == true, "");
	static_assert(std::is_reference::value == true, "");

	// std::is_scalar: T是不是标量类型,基础类型
	static_assert(std::is_scalar::value == false, "");
	static_assert(std::is_scalar::value == true, "");
	static_assert(std::is_scalar::value == false, "");

	// 3.Type properties
	// std::is_abstract: T是不是抽象类
	static_assert(std::is_abstract::value == true, "");
	static_assert(std::is_abstract::value == false, "");
	static_assert(std::is_abstract::value == false, "");

	// std::is_const: T是不是const限定类型
	static_assert(std::is_const::value == true, "");
	static_assert(std::is_const::value == false, "");
	static_assert(std::is_const::value == true, "");

	// std::is_empty: T是不是空类,空类是不存储任何数据的类,即没有非静态数据成员、没有虚函数、也没有虚基类
	static_assert(std::is_empty::value == false, "");
	static_assert(std::is_empty::value == true, "");
	static_assert(std::is_empty::value == false, "");

	// std::is_literal_type: T是不是literal类型,可视为constexpr类型,标量、引用、certain 类,以及这些类型的数组都是literal类型
	static_assert(std::is_literal_type::value == true, "");
	static_assert(std::is_literal_type::value == true, "");
	static_assert(std::is_literal_type::value == false, "");

	// std::is_pod: T是不是POD(Plain Old Data)类型,C语言支持的数据类型,若是类,它需要是trial(普通的)和standard-layout
	static_assert(std::is_pod::value == true, "");
	static_assert(std::is_pod::value == false, "");
	static_assert(std::is_pod::value == false, "");

	// std::is_polymorphic: T是不是多态类
	static_assert(std::is_polymorphic::value == false, "");
	static_assert(std::is_polymorphic::value == true, "");
	static_assert(std::is_polymorphic::value == true, "");

	// std::is_signed: T是不是有符号算术类型
	static_assert(std::is_signed::value == false, "");
	static_assert(std::is_signed::value == true, "");
	static_assert(std::is_signed::value == false, "");

	// std::is_standard_layout: T是不是standard layout类型,如标量;若是类,则要求没有虚函数、虚基类、
	// 所有的非静态数据成员都具有相同的访问权限、在派生类中没有非静态数据成员
	static_assert(std::is_standard_layout::value == true, "");
	static_assert(std::is_standard_layout::value == true, "");
	static_assert(std::is_standard_layout::value == false, "");

	// std::is_trivial: T是不是trivial(普通的)类型,如标量,存储连续;若是类,要求是默认构造/拷贝/移动拷贝/析构,没有虚成员
	static_assert(std::is_trivial::value == true, "");
	static_assert(std::is_trivial::value == true, "");
	static_assert(std::is_trivial::value == true, "");

	// std::is_trivially_copyable: T是不是普通的拷贝类型,如标量;若是类,要求使用隐式定义的拷贝/移动函数、析构函数,没有虚成员
	#ifdef _MSC_VER
		static_assert(std::is_trivially_copyable::value == true, "");
		static_assert(std::is_trivially_copyable::value == true, "");
		static_assert(std::is_trivially_copyable::value == false, "");
	#endif

	// std::is_unsigned: T是不是无符号算术类型
	static_assert(std::is_unsigned::value == true, "");
	static_assert(std::is_unsigned::value == false, "");

	// std::is_volatile: T是不是volatile-qualified类型
	static_assert(std::is_volatile::value == false, "");
	static_assert(std::is_volatile::value == true, "");
	static_assert(std::is_volatile::value == false, "");
	static_assert(std::is_volatile::value == true, "");

	// 4.Type features
	// std::has_virtual_destructor: T是不是具有虚析构函数的类
	static_assert(std::has_virtual_destructor::value == false, "");
	static_assert(std::has_virtual_destructor::value == true, "");

	// std::is_assignable: U是不是赋值给T的类型; std::is_copy_assignable/std::is_move_assignable: T是不是拷贝/移动赋值类型
	static_assert(std::is_assignable::value == true, "");
	static_assert(std::is_assignable::value == false, "");
	static_assert(std::is_copy_assignable::value == true, "");
	static_assert(std::is_copy_assignable::value == true, "");
	static_assert(std::is_copy_assignable::value == false, "");
	static_assert(std::is_move_assignable::value == true, "");
	static_assert(std::is_move_assignable::value == false, "");

	// std::is_constructible: 使用指定的参数,T是不是可构造类型
	// std::is_copy_constructible/std::is_default_constructible/std::is_move_constructible: T是不是拷贝构造/默认构造/移动构造类型
	static_assert(std::is_constructible::value == true, "");
	static_assert(std::is_constructible::value == true, "");
	static_assert(std::is_constructible::value == false, "");
	static_assert(std::is_copy_constructible::value == false, "");
	static_assert(std::is_copy_constructible

::value == true, ""); static_assert(std::is_default_constructible

::value == false, ""); static_assert(std::is_default_constructible::value == true, ""); static_assert(std::is_move_constructible::value == true, ""); static_assert(std::is_move_constructible::value == false, ""); // std::is_destructible: T是不是destructible类型,其析构函数不会被删除,且在派生类中是可访问的 static_assert(std::is_destructible::value == true, ""); static_assert(std::is_destructible::value == true, ""); static_assert(std::is_destructible::value == false, ""); #ifdef _MSC_VER static_assert(std::is_trivially_assignable::value == true, ""); static_assert(std::is_trivially_constructible::value == true, ""); static_assert(std::is_trivially_destructible::value == false, ""); #endif static_assert(std::is_nothrow_assignable::value == true, ""); static_assert(std::is_nothrow_constructible::value == true, ""); static_assert(std::is_nothrow_destructible::value == true, ""); // 5.Type relationships // std::is_base_of: 判断基类是不是派生类的基类 static_assert(std::is_base_of::value == false, ""); static_assert(std::is_base_of::value == true, ""); static_assert(std::is_base_of::value == false, ""); // std::is_convertible: 判断From是不是可以隐式转换到To static_assert(std::is_convertible::value == true, ""); static_assert(std::is_convertible::value == false, ""); static_assert(std::is_convertible::value == true, ""); // std::is_same: 判断U和T是不是属于相同的类型,当且仅当一个是另一种的typedef时,才认为两个不同的类型名代表相同的类型 static_assert(std::is_same::value == false, ""); typedef int integer_type; static_assert(std::is_same::value == true, ""); typedef R R1; static_assert(std::is_same::value == true, ""); // 6.Property queries // std::alignment_of: 返回类型T的对齐值 static_assert(std::alignment_of::value == 4, ""); static_assert(std::alignment_of::value == 1, ""); static_assert(std::alignment_of::value == 8, ""); // std::extent: 获取类型T第i维的范围 typedef int mytype[][24][60]; static_assert(std::extent::value == 0, ""); static_assert(std::extent::value == 24, ""); static_assert(std::extent::value == 60, ""); static_assert(std::extent::value == 0, ""); return 0; }

(3).类型转换(Type transformations):通过对现有类型进行特定的转换来获取新类型的模板类。介绍见以下测试代码:

int test_type_traits_type_transformations()
{
	// 1.Const-volatile qualifications
	// std::add_const/std::remove_const: 对类型T添加/移除const限定符
	typedef std::add_const::type Ax;         // const int
	typedef std::add_const::type Bx;   // const int(unchanged)
	typedef std::add_const::type Cx;  // const int* const
	typedef std::add_const::type Dx;  // int* const(unchanged)
	typedef std::add_const::type Ex;  // const int&(unchanged

	static_assert(std::is_const::value == true, "");
	static_assert(std::is_const::value == true, "");
	static_assert(std::is_const::value == true, "");
	static_assert(std::is_const::value == true, "");
	static_assert(std::is_const::value == false, "");

	typedef std::remove_const::type Fx;
	static_assert(std::is_same::value == true, "");

	// std::add_cv/std::remove_cv: 对类型T添加/移除const volatile限定符
	typedef std::add_cv::type Ay;
	typedef std::add_cv::type By;
	typedef std::add_cv::type Cy;
	typedef std::add_cv::type Dy;

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");

	typedef std::remove_cv::type Fy;
	static_assert(std::is_same::value == true, "");

	// std::add_volatile/std::remove_volatile: 对类型T添加/移除volatile限定符
	typedef std::add_volatile::type Az;            // volatile int
	typedef std::add_volatile::type Bz;   // volatile int(unchanged)
	typedef std::add_volatile::type Cz;  // int* volatile(unchanged)
	typedef std::add_volatile::type Dz;  // volatile int* volatile
	typedef std::add_volatile::type Ez;  // volatile int&(unchanged)

	static_assert(std::is_volatile::value == true, "");
	static_assert(std::is_volatile::value == true, "");
	static_assert(std::is_volatile::value == true, "");
	static_assert(std::is_volatile::value == true, "");
	static_assert(std::is_volatile::value == false, "");

	typedef std::remove_volatile::type Fz;
	static_assert(std::is_same::value == true, "");

	// 2.Compound type alterations
	// std::add_pointer/std::remove_pointer: 获取/移除T的指针类型
	typedef std::add_pointer::type Ap;        // int*
	typedef std::add_pointer::type Bp;  // const int*
	typedef std::add_pointer::type Cp;       // int*
	typedef std::add_pointer::type Dp;       // int**
	typedef std::add_pointer::type Ep;   // int(*)(int)

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	typedef std::remove_pointer::type Fp;
	static_assert(std::is_same::value == true, "");

	// std::add_lvalue_reference/std::add_rvalue_reference:获取T左值/右值引用类型;std::remove_reference: 获取T非引用类型
	typedef std::add_lvalue_reference::type Aq;    // int&
	typedef std::add_lvalue_reference::type Bq;   // int&
	typedef std::add_lvalue_reference::type Cq;  // int&
	typedef std::add_lvalue_reference::type Dq;   // int*&

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	typedef std::add_rvalue_reference::type Ar;    // int&&
	typedef std::add_rvalue_reference::type Br;   // int&  (no change)
	typedef std::add_rvalue_reference::type Cr;  // int&& (no change)
	typedef std::add_rvalue_reference::type Dr;   // int*&&

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	typedef std::remove_reference::type Fq;
	typedef std::remove_reference::type Fr;
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");

	// std::decay: 获得T的decay(退化)类型
	typedef std::decay::type As;           // int
	typedef std::decay::type Bs;          // int
	typedef std::decay::type Cs;         // int
	typedef std::decay::type Ds;    // int
	typedef std::decay::type Es;        // int*
	typedef std::decay::type Fs;      // int(*)(int)

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == false, "");

	// std::make_signed/std::make_unsigned: 获取与T对应的带符号/无符号类型,并保留所有cv限定符
	typedef std::make_signed::type At;                // int
	typedef std::make_signed::type Bt;           // int
	typedef std::make_signed::type Ct;     // const int

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	typedef std::make_unsigned::type Au;                // unsigned int
	static_assert(std::is_same::value == true, "");

	// std::remove_all_extents/std::remove_extent: 移除所有/数组范围
	typedef std::remove_all_extents::type Av;                // int
	typedef std::remove_all_extents::type Bv;            // int
	typedef std::remove_all_extents::type Cv;        // int
	typedef std::remove_all_extents::type Dv;          // int
	typedef std::remove_all_extents::type Ev;      // const int

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	typedef std::remove_extent::type Cw;        // int[60]
	typedef std::remove_extent::type Dw;          // int[60]
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == false, "");

	// std::underlying_type: 获取枚举类型T的基础类型
	enum class Aa { a, b, c };
	enum Ba : short { x, y, z };
	typedef std::underlying_type::type A_under;   // int
	typedef std::underlying_type::type B_under;   // short

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");

	// 3.Other type generators
	// std::aligned_storage: 将内存分配与对象创建分离时使用
	// std::aligned_union: Obtains a POD type suitable for use as storage for any object whose type is listed in Types, and a size of at least Len

	// std::common_type: 在类型列表中获取所有类型都可以转换为的通用类型
	typedef std::common_type::type Ab;           // int
	typedef std::common_type::type Bb;              // double
	typedef std::common_type::type Cb;					   // B
	typedef std::common_type::type Db;    // int

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == true, "");

	// std::conditional: 根据cond是true还是false,获取成员类型
	typedef std::conditional::type Ac;                      // int
	typedef std::conditional::type Bc;                     // float
	typedef std::conditional::value, long, int>::type Cc; // long
	typedef std::conditional::value, long, int>::type Dc; // int

	static_assert(std::is_same::value == true, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == false, "");
	static_assert(std::is_same::value == true, "");

	// std::enable_if: 如果条件满足则启用类型
	// std::result_of: Obtains the result type of a call to Fn with arguments of the types listed in ArgTypes

	return 0;
}

以上代码主要参考:cplusplus  cppreference

GitHub:https://github.com/fengbingchun/Messy_Test

你可能感兴趣的:(type_traits)