(C++模板编程):萃取技术及fixed traits -- const及引用修饰符的移除 、退化(decay)技术

萃取技术及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函数
  • 输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值