本文阐述c++中的type_traits技术,即类型萃取。
示例代码 通过如下测试程序,练习type traits的使用。
1 2 3 4 5 template <typename T>struct my_strait { using has_trivial_default_copy_constructor = __true_type; };
设计两个类,分别具有nontrivial的copy-assignment和trivial的copy-assignment,很容易想到两个典型的类:String和Complex,我们写出他们的定义,其中String包含了自定义的nontrivial-copy-assignment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 class String { friend ostream &operator <<(ostream &os, const String &rhs) { cout << rhs.ps; return os; } private : char *ps{}; size_t len{}; public : String () = default ; explicit String (const char *s) { len = strlen (s); ps = new char [len + 1 ]; strncpy (ps, s, len); ps[len] = '\0' ; } String (const String &s) : ps (new char [s.len + 1 ]), len (s.len) { strncpy (ps, s.ps, len); ps[len] = '\0' ; } String &operator =(const String &s) { if (this != &s) { delete [] ps; len = s.len; ps = new char [len + 1 ]; strncpy (ps, s.ps, len); ps[len] = '\0' ; } return *this ; } ~String () { delete [] ps; } }; class Complex { friend ostream &operator <<(ostream &os, const Complex &rhs) { cout << rhs.real << " + " << rhs.imag << "i" ; return os; } private : double real{}; double imag{}; public : Complex () = default ; Complex (double r, double i) : real (r), imag (i) {} };
为这两个类添加了重载<<输出运算符友元函数,方便我们输出对象的内容。
提供两个类相关的特化版本my_trait:
1 2 3 4 5 6 7 8 9 10 11 template <>struct my_strait <String>{ using has_trivial_default_copy_assign = __false_type; }; template <>struct my_strait <Complex>{ using has_trivial_default_copy_assign = __true_type; };
给出一个模板函数copy,其会根据传入的参数实际类型,是否具有trivial的默认拷贝赋值运算符,调用不同的重载函数copy_aux:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 template <typename T>void copy_aux (T &lhs, const T &rhs, __true_type) { cout << "this is true type copy\n" ; lhs = rhs; } template <typename T>void copy_aux (T &lhs, const T &rhs, __false_type) { cout << "this is false type copy\n" ; lhs = rhs; } template <typename T>void copy (T &lhs, const T &rhs) { using Temp = typename my_strait<T>::has_trivial_default_copy_assign; copy_aux (lhs, rhs, Temp ()); }
编写如下main函数测试,观察copy函数的执行情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int main () { cout <<"=============String================\n" ; String s1 ("hello" ) ; String s2; copy (s2, s1); cout << s1 << endl; cout << s2 << endl; cout <<"=============Complex================\n" ; Complex c1 (1.2 , 3.4 ) ; Complex c2; copy (c2, c1); cout << c1 << endl; cout << c2 << endl; cout <<"=============double================\n" ; double a = 13.2 ; double b = 2.1 ; copy (b, a); cout << a << endl; cout << b << endl; return 0 ; }
执行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 =============String================ this is false type copy hello hello =============Complex================ this is true type copy 1.2 + 3.4i 1.2 + 3.4i =============double================ this is true type copy 13.2 13.2
我的电脑环境是Windows11系统,clion 2022,在Linux平台上应该也是一样的。