類型萃取是一種經常使用的編程技巧,其目的是實現不一樣類型數據面對同一函數實現不一樣的操做,如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]; } } }
若有不足,但願批評指正。
指針