刚刚我们接触过模板类,类似于这样的:
在这个类中,我们如何知道它是什么类型的呢?这里,我们可以在类中加入一个内嵌类型,如:
这样就可以知道它是用户自定义的还是本身类型就拥有的,我们用到了类型萃取的方式。我们把__IsPodType叫做内嵌型别。
当我们遇到其他类型时,就将__IsPodType定义为__FalseType;
当遇到自定义类型时,就将__IsPodType定义为__TrueType;
说起这种书写方式,将template<>称为类型的特化。
举一个实在点的例子吧:
#include<iostream>
using namespace std;
struct __TrueType
{bool Get(){return true;}
};struct __FalseType
{bool Get(){return false;}
};template<class __Tp>
struct TypeTraits
{typedef __FalseType __IsPodType;
};template<>
struct TypeTraits<int> //在这里,非自定义类型只列出了int,char,float等这几种,其实还有很多类型,像long long,double,unsigned char等等
{typedef __TrueType __IsPodType;
};template<>
struct TypeTraits<char>
{typedef __TrueType __IsPodType;
};template<>
struct TypeTraits<long>
{typedef __TrueType __IsPodType;
};template<>
struct TypeTraits<unsigned int>
{typedef __TrueType __IsPodType;
};template<>
struct TypeTraits<float>
{typedef __TrueType __IsPodType;
};template<class __Tp>
void Copy(const __Tp* src, __Tp* dst,size_t size,__TrueType)
{memcpy(dst,src,size*sizeof(__Tp)); //拷贝的内置类型
}template<class __Tp>
void Copy(const __Tp* src, __Tp* dst,size_t size,__FalseType)
{int i = 0;for(i = 0; i < size; i++){dst[i] = src[i];}
}
<span style="font-family: Arial, Helvetica, sans-serif;">// 使用萃取判断类型的Get函数判断是否是 POD类型来处理</span>
//template<class __Tp>
//void Copy(const __Tp* src, __Tp* dst,size_t size) //Copy的另外一种写法,不传入类型
//{
// if(TypeTraits<__Tp>::__IsPodType().Get()) //if判断就可以直接写一个函数,,是上述两个Copy的结合
// {
// memcpy(dst,src,size*sizeof(__Tp));
// }
// else
// {
// int i = 0;
// for(i = 0; i < size; i++)
// {
// dst[i] = src[i];
// }
// }
//}template<class __Tp>
void print(const __Tp* arr,size_t size)
{int i = 0;for(i = 0; i < size; i++){cout<<arr[i]<<" ";}
}int main()
{int arr1[] = {1,3,5,7,9};int arr2[10];int size = sizeof(arr1)/sizeof(arr1[0]);Copy(arr1,arr2,size,TypeTraits<int>::__IsPodType());/*Copy(arr1,arr2,size);*/print(arr2,size);return 0;
}
以上是数组的拷贝,用了类型萃取的方式。详细一点说类型萃取技术的由来就是,由于c++模板中类的参数是抽象的,我们不能在模板类中直接获得它的具体特征,我们就用类型萃取(trait)的方式,来抽取类型的具体特征,知道它是什么类型,比如内置类型,自定义类型。
我们可以看到很多模板类的特化,这也是类型萃取的一个基本思想。