模板(三):模板之类型萃取(TypeTraits)
程序员文章站
2022-06-10 14:38:25
...
所谓理解 通常不过是误解的总和.
——《斯普特尼克恋人》
类型萃取,是C++中的一种编程技术。使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,因为不同的类型具有不同的特性,当我们希望对模板传递的不同类型进行不同的操作的时候,同时我们又不希望改变该模板的封装方式。我们可以通过这种技术,对传入的不同类型进行不同的原理操作。
这里我进行一个对于自创类SeqList类(对STL中vector的模拟)的类型萃取举例,情景说明:这里我想要对模板类SeqList进行拷贝,涉及到一个问题。如果我的元素类型是string的话,我必须进行深拷贝,否则就会出现崩溃的情况,这是对内存的使用出现问题。当我的元素类型是int、float、char等平凡类型(即POD:plain old data,基本类型,指在C++ 中与 C兼容的类型,可以按照 C 的方式处理,这些类型的拷贝不会涉及到内存的使用异常),我就可以使用浅拷贝,这样比起深拷贝提高了效率。
这个时候,我通过在SeqList类中进行类型萃取,就可以实现两种不同的拷贝方式:
//定义两个空类
struct __TrueType{};
struct __FalseType{};
//一般类型及特化(内嵌重定义IsPODType)
template<class T>
struct __TypeTraits{ typedef __FalseType IsPODType; };
template<>
struct __TypeTraits<int>{ typedef __TrueType IsPODType; };
//实现功能函数(用__TrueType/__FalseType实现重载)
template <class T>
T* __TypeCopy(T* dst, const T* src, size_t n, __TrueType){
cout << "__TrueType:" << typeid(T).name() << endl;
return (T*)memcpy(dst, src, n*sizeof(T)); //浅拷贝,调用memcpy
}
template <class T>
T* __TypeCopy(T* dst, const T* src, size_t n, __FalseType){
cout << "__TrueType:" << typeid(T).name() << endl;
for (size_t i = 0; i < n; ++i){ //深拷贝,进行了 operator= 调用
dst[i] = src[i];
}
return dst;
}
//对外接口(实现IsPODType的__TrueType和__FalseType的转换)
template <class T>
T* TypeCopy(T* dst, const T* src, size_t n){
return __TypeCopy(dst, src, n, __TypeTraits<T>::IsPODType());
}
int main(){
int a1[3] = { 1, 2, 3 };
int a2[3] = { 0, 0, 0 };
string s1[3] = { "1", "2", "3" };
string s2[3] = { "0", "0", "0" };
TypeCopy(a1, a2, 3);
TypeCopy(s1, s2, 3);
return 0;
}
//typeid可以获取到一个类型的名称,但是不能拿来做变量的声明。
类型萃取流程图
注意 __TypeTraits<T>::IsPODType
是一个类型,类型加一个括号生成一个匿名对象,对象才能在函数中传参,函数的参数传参是传对象,所以类型加括号生成匿名对象传给形参.