欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

模板(三):模板之类型萃取(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)

注意
__TypeTraits<T>::IsPODType是一个类型,类型加一个括号生成一个匿名对象,对象才能在函数中传参,函数的参数传参是传对象,所以类型加括号生成匿名对象传给形参.

  
  
模板(一):模板与非类型模板参数&模板的模板参数
模板(二):模板的特化与模板的分离编译