资源网站很难做,烟台网站建设电话,沈阳做网站 熊掌号,泰州市做网站const修饰符的移除
让你来写移除const修饰符#xff0c;你会怎么样来写#xff1f; #x1f602;#x1f602;trait类模板#xff0c;如下 #include iostream// 泛化版本
templatetypename T
struct RemoveConst
{using type T;
};// 特化版本
template…const修饰符的移除
让你来写移除const修饰符你会怎么样来写 trait类模板如下 #include iostream// 泛化版本
templatetypename T
struct RemoveConst
{using type T;
};// 特化版本
templatetypename T
struct RemoveConstconst T
{using type T;
};// 根据需要可能还要增加其他特化版本
templatetypename T
using RemoveConst_t typename RemoveConstT::type;int main()
{// nca 是int类型// c标准库中的std::remove_const也比较类似RemoveConst_tconst int nca 15;// 可以给nca重新赋值nca 18;return 0;
}退化技术
某些类型一旦传递给函数模板通过函数模板来推断相关的类型那么推断出来的类型就会产生退化。所谓退化decay就是把类型中的一些修饰符丢弃了。例如const int中的const丢弃后就变成int类型那么对于const int类型int类型就是一种退化的表现。c标准库中有一个类模板std::decay这个类模板的作用就是把一个类型退化掉就是把类型中的一些修饰符丢掉。 std::decayconst int::type nb 28;// nb的类型为int类型std::cout nb的类型为 typeid(decltype(nb)).name() std::endl;如何实现一个类似std::decay功能的trait类模板呢
// b.cpp
int g_array[10];// main.cpp
#include iostream// 泛化版本
templatetypename T
struct RemoveReference
{using type T;
};// 特化版本
templatetypename T
struct RemoveReferenceT
{using type T;
};
templatetypename T
struct RemoveReferenceT // 这个特化能适应 const T应该是伴随我一生难以理解的噩梦了
{using type T;
};// 泛化版本
templatetypename T
struct RemoveConst
{using type T;
};// 特化版本
templatetypename T
struct RemoveConstconst T
{using type T;
};// 根据需要可能还要增加其他特化版本
templatetypename T
using RemoveConst_t typename RemoveConstT::type;templatetypename T
struct RemoveCR : RemoveConsttypename RemoveReferenceT::type
{ // 把const和引用修饰符去掉
};templatetypename T
using RemoveCR_t typename RemoveCRT::type;// Decay的trait类模板
// 泛化版本
templatetypename T
struct Decay : RemoveCRT
{
};// 特化版本这个特化版本没有继承任何父类
// 有边界数组转换成指针
templatetypename T,std::size_t size
struct DecayT[size]
{using type T*;
};// 无边界数组转换成指针
templatetypename T
struct DecayT[]
{using type T*;
};extern int g_array[];int main()
{RemoveCR_tconst int rcrobj 15; // rcrobj为int类型只能叹为观止惊叹rcrobj鬼斧神工地成了int类型int arr[2] { 1,2 };Decaydecltype(arr)::type my_array;std::cout my_array的类型为: typeid(decltype(my_array)).name() std::endl;Decaydecltype(g_array)::type my_array_2;std::cout my_array_2的类型为 typeid(decltype(my_array_2)).name() std::endl;return 0;
}上述函数代表类型void()可以使用函数指针指向某种函数类型如果指向void()函数指针应该是void(*)()如果不为函数名退化为函数指针写一个Decay的特化版本那么传入testFunc2这个函数类型 得到的返回类型依旧是void()换句话说传入什么类型就返回什么类型 #include iostream// 泛化版本
templatetypename T
struct RemoveReference
{using type T;
};// 特化版本
templatetypename T
struct RemoveReferenceT
{using type T;
};
templatetypename T
struct RemoveReferenceT // 这个特化能适应 const T应该是伴随我一生难以理解的噩梦了
{using type T;
};// 泛化版本
templatetypename T
struct RemoveConst
{using type T;
};// 特化版本
templatetypename T
struct RemoveConstconst T
{using type T;
};// 根据需要可能还要增加其他特化版本
templatetypename T
using RemoveConst_t typename RemoveConstT::type;templatetypename T
struct RemoveCR : RemoveConsttypename RemoveReferenceT::type
{ // 把const和引用修饰符去掉
};templatetypename T
using RemoveCR_t typename RemoveCRT::type;// Decay的trait类模板
// 泛化版本
templatetypename T
struct Decay : RemoveCRT
{
};// 特化版本这个特化版本没有继承任何父类
// 有边界数组转换成指针
templatetypename T,std::size_t size
struct DecayT[size]
{using type T*;
};// 无边界数组转换成指针
templatetypename T
struct DecayT[]
{using type T*;
};extern int g_array[];// 简单的函数
void testFunc2()
{std::cout testFunc2()执行了 std::endl;
}void rfunc()
{std::cout rfunc执行了 std::endl;
}int main()
{RemoveCR_tconst int rcrobj 15; // rcrobj为int类型只能叹为观止惊叹rcrobj鬼斧神工地成了int类型int arr[2] { 1,2 };Decaydecltype(arr)::type my_array;std::cout my_array的类型为: typeid(decltype(my_array)).name() std::endl;Decaydecltype(g_array)::type my_array_2;std::cout my_array_2的类型为 typeid(decltype(my_array_2)).name() std::endl;// 2Decaydecltype(testFunc2)::type rfunc;std::cout rfunc类型为: typeid(decltype(rfunc)).name() std::endl;rfunc();return 0;
}现在容易理解写一个Decay特化版本把函数名退化成函数指针这件事了 因为函数可能有任何的返回类型以及任何数量和类型的参数所以这个Decay的特化版本比较特殊 需要可变参模板来实现 #include iostream// 泛化版本
templatetypename T
struct RemoveReference
{using type T;
};// 特化版本
templatetypename T
struct RemoveReferenceT
{using type T;
};
templatetypename T
struct RemoveReferenceT // 这个特化能适应 const T应该是伴随我一生难以理解的噩梦了
{using type T;
};// 泛化版本
templatetypename T
struct RemoveConst
{using type T;
};// 特化版本
templatetypename T
struct RemoveConstconst T
{using type T;
};// 根据需要可能还要增加其他特化版本
templatetypename T
using RemoveConst_t typename RemoveConstT::type;templatetypename T
struct RemoveCR : RemoveConsttypename RemoveReferenceT::type
{ // 把const和引用修饰符去掉
};templatetypename T
using RemoveCR_t typename RemoveCRT::type;// Decay的trait类模板
// 泛化版本
templatetypename T
struct Decay : RemoveCRT
{
};// 特化版本这个特化版本没有继承任何父类
// 有边界数组转换成指针
templatetypename T,std::size_t size
struct DecayT[size]
{using type T*;
};// 无边界数组转换成指针
templatetypename T
struct DecayT[]
{using type T*;
};extern int g_array[];// 简单的函数
void testFunc2()
{std::cout testFunc2()执行了 std::endl;
}// 3
templatetypename T,typename... Args
struct DecayT(Args...) // 返回类型是T参数是Args...
{using type T(*)(Args...);
};int main()
{RemoveCR_tconst int rcrobj 15; // rcrobj为int类型只能叹为观止惊叹rcrobj鬼斧神工地成了int类型int arr[2] { 1,2 };Decaydecltype(arr)::type my_array;std::cout my_array的类型为: typeid(decltype(my_array)).name() std::endl;Decaydecltype(g_array)::type my_array_2;std::cout my_array_2的类型为 typeid(decltype(my_array_2)).name() std::endl;#if 0// 2Decaydecltype(testFunc2)::type rfunc;std::cout rfunc类型为: typeid(decltype(rfunc)).name() std::endl;rfunc();
#endif // 3Decaydecltype(testFunc2)::type rfunc_1;std::cout rfunc类型为 typeid(decltype(rfunc_1)).name() std::endl;rfunc_1 testFunc2;rfunc_1();return 0;
}别名模板的威力 通过别名模板把Decay::type类型名简化成Decay_t代码如下
templatetypename T
using Decay_t typename DecayT::type;于是main()函数中的代码可以写成
Decaydecltype(testFunc2)::type rfunc;就可以写成
Decay_tdecltype(testFunc2) rfunc;