Type Traits
是 C++11 中的一种模板元编程技术,它提供了一系列的模板类和函数,用于在编译时查询和操作类型信息。这些类型特征可以用于泛型编程中,帮助我们编写更加灵活、通用和安全的代码。
例如:判断一个类型是否为指针类型、是否为整数类型、是否可以进行拷贝构造等等。这使得我们可以根据类型的属性来做出不同的编译时决策,从而避免在运行时出现错误或者不必要的性能损失。
1. 基本类型
#if 0 #include <iostream> #include <type_traits> using namespace std; class MyClass {}; void i(){} void test() { int a = 100; double b = 3.14; int* c = nullptr; int& d = a; int&& e = 200; enum MyEnum{} f; union MyUnion {} g; MyClass h; cout << "int a = 100;" << endl; cout << "double b = 3.14;" << endl; cout << "int* c = nullptr;" << endl; cout << "int& d = a;" << endl; cout << "int&& e = 200;" << endl; cout << "enum MyEnum{} f;" << endl; cout << "union MyUnion {} g;" << endl; cout << "MyClass h;" << endl; cout << "void i(){}" << endl; cout << endl; // bool, char, signed char, unsigned char, wchar_t, char16_t, char32_t, short, int, long, long long cout << "是否整数:" << endl; cout << "a\t" << is_integral<decltype(a)>::value << endl; // float, double, long double cout << "是否浮点数:" << endl; cout << "b\t" << is_floating_point<decltype(b)>::value << endl; cout << "是否指针:" << endl; cout << "c\t" << is_pointer<decltype(c)>::value << endl; cout << "是否空指针:" << endl; cout << "c\t" << is_null_pointer<decltype(c)>::value << endl; cout << "是否引用:" << endl; cout << "d\t" << is_reference<decltype(d)>::value << endl; cout << "e\t" << is_reference<decltype(e)>::value << endl; cout << "是否左值引用:" << endl; cout << "d\t" << is_lvalue_reference<decltype(d)>::value << endl; cout << "是否右值引用:" << endl; cout << "e\t" << is_rvalue_reference<decltype(e)>::value << endl; cout << "是否枚举:" << endl; cout << "f\t" << is_enum<decltype(f)>::value << endl; cout << "是否联合体:" << endl; cout << "g\t" << is_union<decltype(g)>::value << endl; cout << "是否类:" << endl; cout << "h\t" << is_class<decltype(h)>::value << endl; cout << "是否函数:" << endl; cout << "i\t" << is_function<decltype(i)>::value << endl; } int main() { test(); return 0; } #endif
2. CV 限定符
#if 0 #include <iostream> #include <type_traits> using namespace std; void test() { const int a = 10; const int* b = nullptr; int* const c = nullptr; // 引用的对象是 cons int const int& d = a; // 引用的对象是 const int&& const int&& e = 10; cout << "是否 const:" << endl; cout << "a\t" << is_const<decltype(a)>::value << endl; cout << "b\t" << is_const<decltype(b)>::value << endl; cout << "c\t" << is_const<decltype(c)>::value << endl; cout << "d\t" << is_const<decltype(d)>::value << endl; cout << "e\t" << is_const<decltype(e)>::value << endl; volatile int f = 10; volatile int* g = nullptr; int* volatile h = nullptr; cout << "是否 volatile:" << endl; cout << "f\t" << is_volatile<decltype(f)>::value << endl; cout << "g\t" << is_volatile<decltype(g)>::value << endl; cout << "h\t" << is_volatile<decltype(h)>::value << endl; } int main() { test(); return 0; } #endif
3. 关系判断
#if 0 #include <iostream> #include <type_traits> using namespace std; class Base {}; class Derived : public Base {}; void test() { Base base1, base2; Derived s1, s2; cout << "是否同类型:" << endl; cout << "p1 p2\t" << is_same<decltype(base1), decltype(base2)>::value << endl; cout << "p1 Person\t" << is_same<decltype(base1), Base>::value << endl; cout << "是否是基类:" << endl; cout << "Base 是 Derived 基类\t" << is_base_of<Base, Derived>::value << endl; // 判断一个类型是否可以隐式转换为另一个类型。 cout << "是否可以转换类型:" << endl; cout << "Base 转换 Derived 类型\t" << is_convertible<Base, Derived>::value << endl; cout << "Derived 转换 Base 类型\t" << is_convertible<Derived, Base>::value << endl; cout << "double* 转换 int 类型\t" << is_convertible<double*, int>::value << endl; cout << "int 转换 double* 类型\t" << is_convertible<int, double*>::value << endl; } int main() { test(); return 0; } #endif
4. 修饰符
#if 1 #include <iostream> #include <type_traits> using namespace std; template<class T> struct RemomveAllPointers { using type = T; }; template<class T> struct RemomveAllPointers<T*> { using type = typename RemomveAllPointers<T>::type; }; // 1. 移除修饰符 void test01() { const int a = 10; volatile int b = 20; int temp = 10; int& c = temp; int&& d = 10; int* e = nullptr; int** f = nullptr; cout << "移除 const:" << endl; cout << typeid(remove_const<decltype(a)>::type).name() << endl; cout << "移除 volatile:" << endl; cout << typeid(remove_volatile<decltype(b)>::type).name() << endl; cout << "移除引用:" << endl; cout << typeid(remove_reference<decltype(c)>::type).name() << endl; cout << typeid(remove_reference<decltype(d)>::type).name() << endl; // 指针降级 cout << "移除一级指针:" << endl; cout << typeid(remove_pointer<decltype(e)>::type).name() << endl; cout << "移除多级指针" << endl; cout << typeid(RemomveAllPointers<decltype(f)>::type).name() << endl; } // 2. 增加修饰符 void test02() { int a = 100; // 1. 增加 const 修饰符 using NewConstType = add_const<decltype(a)>::type; NewConstType aa = 100; // 表达式必须是可修改的左值 // aa = 200; // 通过 t 版本直接获得类型 // add_const_t<decltype(a)> aaa = 100; // aaa = 200; // 2. 增加指针修饰符 using NewPointerType = add_pointer<decltype(a)>::type; cout << typeid(NewPointerType).name() << endl; // 3. 增加左值引用修饰符 using NewLvalueType = add_lvalue_reference<decltype(a)>::type; // 非常量引用的初始值必须为左值 // NewLvalueType bb = 200; // 4. 增加右值引用修饰符 using NewRvalueType = add_rvalue_reference<decltype(a)>::type; NewRvalueType cc = 100; } int main() { test02(); return 0; } #endif
5. 类相关
#if 1 #include <iostream> #include <type_traits> using namespace std; class A { public: A() = delete; A(const A&) = delete; A(A&&) = delete; virtual ~A() {}; }; class B { virtual void func() {} }; class C { virtual void func() = 0; }; void test() { const int a = 10; // 检查类是否是空的(没有非静态数据成员、虚函数或基类) cout << "A\t" << is_empty<A>::value << endl; // 检查类是否具有多态性(至少一个虚函数) cout << "B\t" << is_polymorphic<B>::value << endl; // 检查类是否是抽象类(至少一个纯虚函数) cout << "C\t" << is_abstract<C>::value << endl; // 判断是否可以进行默认构造 cout << is_default_constructible<A>::value << endl; cout << is_copy_constructible<A>::value << endl; cout << is_move_constructible<A>::value << endl; cout << is_destructible<A>::value << endl; cout << has_virtual_destructor<A>::value << endl; } int main() { test(); return 0; } #endif