萃取技术及fixed traits
【const修饰符的移除】
//泛化版本 template <typename T> struct RemoveConst { using type = T; }; //特化版本 template <typename T> struct RemoveConst<const T> { using type = T; }; //根据需要增加其他特化版本.... template <typename T> using RemoveConst_t = typename RemoveConst<T>::type;
- 调用
RemoveConst_t<const int> nca = 15; //nca是int类型 nca = 18; //可以给nca重新赋值
- const修饰符的移除RemoveConst类模板,与C++标准库里std::remove_const比较类似。
退化(decay)技术
【引例】
template<typename T> void myfunc(T tmprv) { cout << "---------------------begin------------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; //显示T类型 cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv类型 cout << "----------------------end-------------------------" << endl; } void testFunc() {}
- 调用
const int a = 16; const int& b = a; const int&& c = 18; int array[5] = { 1,2,3,4,5 }; myfunc(a); myfunc(b); myfunc(c); myfunc(array); myfunc(testFunc);
- 输出
- const修饰符和&、&&修饰符被丢弃,数组类型变成指针类型,函数名变成了函数指针等,都是类型上的退化表现。
【std::decay】
- 该类模板的作用就是把类型退化掉(把类型中的修饰符丢弃掉)。
std::decay<const int&>::type nb = 26; cout << "nb的类型为:" << typeid(decltype(nb)).name() << endl; //nb类型为int类型。
- 输出
【去掉 const 和引用】
//泛化版本 template<typename T> struct RemoveReference { using type = T; }; //特化版本 template<typename T> struct RemoveReference<T&> { using type = T; }; template<typename T> struct RemoveReference<T&&> { using type = T; }; template <typename T> using RemoveReference_t = typename RemoveReference<T>::type; //------------------------------------- //泛化版本 template <typename T> struct RemoveConst { using type = T; }; //特化版本 template <typename T> struct RemoveConst<const T> { using type = T; }; //根据需要增加其他特化版本.... template <typename T> using RemoveConst_t = typename RemoveConst<T>::type; //---------------------------------------- template <typename T> struct RemoveCR :RemoveConst<typename RemoveReference<T>::type> //把const和引用修饰符去掉 { }; template <typename T> using RemoveCR_t = typename RemoveCR<T>::type; /*template <typename T> using RemoveCR_t = RemoveConst_t<typename RemoveReference_t<T>>;*/
- 调用
RemoveCR_t<const int&&> rcrobj = 16; //rcrobj为int类型。
【数组类型变成指针类型】
//泛化版本 template<typename T> struct Decay :RemoveCR<T> { }; //特化版本,处理数组,该特化版本没有继承任何父类 //有边界数组转换成指针 template<typename T,std::size_t size> struct Decay<T[size]> { using type = T*; }; //无边界数组转换成指针 template<typename T> struct Decay<T[]> { using type = T*; };
- 调用
int arr[2] = { 1,2 }; Decay<decltype(arr)>::type myarray; cout << "myarray类型为:" << typeid(decltype(myarray)).name() << endl; //int * extern int g_array[]; //int [] Decay<decltype(g_array)>::type myarray2; cout << "myarray2类型为:" << typeid(decltype(myarray2)).name() << endl; //int *
【函数名变成函数指针】
【引例】
void testFunc2() { cout << "testFunc2()执行了" << endl; }
- 函数类型:由函数返回值和函数参数决定,testFunc2代表的函数类型void()
- 可以利用函数指针指向某种函数类型,若要指向testFunc2,那么函数指针的类型就应该void(*)()
void (*p) () = testFunc2; //定义了一个函数指针,指向testFunc2函数 p(); //调用p指向的函数,调用的是testFunc2函数。
- 如果不为“函数名退化成函数指针”写一个Decay的特化版本,观察一些测试代码:给进去的是函数类型,返回的依旧是函数类型。
//全局环境定义函数 void rfunc() { cout << "rfunc执行了!" << endl; }
Decay<decltype(testFunc2)>::type rfunc; //表面看起来此代码行定义了一个函数类型的变量rfunc,实际理解成函数声明更好 //类似于这种代码行的感觉: void rfunc(); cout << "rfunc类型为:" << typeid(decltype(rfunc)).name() << endl; rfunc(); //调用rfunc函数
- 输出
【函数名变成函数指针功能实现】
//函数名变成了函数指针等 template <typename T,typename... Args> struct Decay<T(Args...)> //返回类型是T,参数Args.... { using type = T(*)(Args...); }; template <typename T> using Decay_t = typename Decay<T>::type;
- 调用
Decay_t<decltype(testFunc2)> rfunc; cout << "rfunc类型为:" << typeid(decltype(rfunc)).name() << endl; rfunc = testFunc2; //给函数指针赋值 rfunc(); //相当于调用了testFunc2函数
- 输出