类型萃取是一种经常使用的编程技巧,其目的是实现不一样类型数据面对同一函数实现不一样的操做,如STL中cout的实现,它与类封装的区别是,咱们并不用知道咱们所调用的对象是什么类型,类型萃取是编译器后知道类型,先实现,而类的封装则是先定义类型,后实现方法。在这里咱们能够用模板的特化实现其编程思想。编程
咱们以memcpy为例,当咱们拷贝的是基本类型时,只用拷贝所传递指针上的数据,若是是string类型呢,咱们则须要在堆上开辟空间,所传递的指针若是被直接复制,则有可能(vs下的string类型的实现原理是若字符串不长则以数组保存,若字符串过长,则经过指针在堆上开辟空间进行保存)出现同一地址,析构两次这样的常见错误。
数组
在这里咱们须要在一个头文件中定义两个类,用来区分是不是基本类型,代码以下:
ide
struct __TrueType//基本类型 { bool Get() { return true; } }; struct __FalseType//非基本类型 { bool Get() { return false; } };
其次定义类模板,使基本类型特化,非基本类型则不需用特化:
函数
template <class _Tp>//非基本类型不特化 struct TypeTraits { typedef __FalseType __IsPODType; }; template <>//基本类型的全特化 struct TypeTraits< bool> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< char> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< unsigned char > { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< short> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< unsigned short > { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< int> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< unsigned int > { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< long> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< unsigned long > { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< long long > { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< unsigned long long> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< float> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< double> { typedef __TrueType __IsPODType; }; template <> struct TypeTraits< long double > { typedef __TrueType __IsPODType; }; template <class _Tp> struct TypeTraits< _Tp*>//指针类型的偏特化 { typedef __TrueType __IsPODType; };
作完这些咱们还须要memcpy的实现:
测试
template <class T> void Copy(const T* src, T* dst, size_t size) { //cout << "__TrueType:" << typeid(T).name() << endl;//测试用 if (TypeTraits <T>::__IsPODType().Get())//返回值为真(是基本类型)则调用memcpy { memcpy(dst, src, size*sizeof (T)); } else { for (size_t i = 0; i < size; ++i)/*不是基本类型,则用赋值运算符的重载实现memcpy*/ { dst[i] = src[i]; } } }
若有不足,但愿批评指正。
指针