剛剛我們接觸過模板類,類似于這樣的:
在這個類中,我們如何知道它是什么類型的呢?這里,我們可以在類中加入一個內嵌類型,如:
這樣就可以知道它是用戶自定義的還是本身類型就擁有的,我們用到了類型萃取的方式。我們把__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)的方式,來抽取類型的具體特征,知道它是什么類型,比如內置類型,自定義類型。
我們可以看到很多模板類的特化,這也是類型萃取的一個基本思想。