一、模闆的定義
1.類模闆
template <class T>
class compare
{
public:
bool IsEqual(T t1, T t2)
{
return t1 == t2;
}
};
int main()
{
char str1[] = "Hello";
char str2[] = "Hello";
compare<int> c1;
compare<char *> c2;
cout << c1.IsEqual(, ) << endl; //比較兩個int類型的參數
cout << c2.IsEqual(str1, str2) << endl; //比較兩個char *類型的參數
return ;
}
2.函數模闆
bool IsEqual(T t1, T t2)
{
return t1 == t2;
}
int main()
{
char str1[] = "Hello";
char str2[] = "Hello";
cout << IsEqual(, ) << endl;
cout << IsEqual(str1, str2) << endl;
return ;
}
二、模闆特化
上述代碼中,比較字元串是否相等,由于傳入的參數是char *類型的,IsEqual函數模闆隻是簡單的比較傳入參數的值,即兩個指針是否相等,是以結果為false。顯然,這與我們的初衷不符。是以,上述模闆需要對char *類型進行特别處理,即特化。
1.類模闆特化
template <> //告訴編譯器這是一個特化的模闆
class compare<char *> //特化(char*)
{
public:
bool IsEqual(char* t1, char* t2)
{
return strcmp(t1, t2) == ; //使用strcmp比較字元串
}
};
注意,如果是在類特化外部定義成員時,成員之前不能加template<>标記。
另外,我們可以隻特化成員而不特化類,比如vector中,我們可以隻特化push_back操作:
template<>
void vector<const char *>::push_back(const char *const &val)
{
//...
}
類類型vector
2.函數模闆特化
template <>
bool IsEqual(char* t1, char* t2) //函數模闆特化
{
return strcmp(t1, t2) == ;
}
三、模闆偏特化
1.類模闆的偏特化
當有多個模闆形參時,我們可以隻特化一部分形參而不是全部。
c++标準庫中的類vector的定義就是一個例子:
template <class T, class Allocator>
class vector { // … // };
template <class Allocator>
class vector<bool, Allocator> { //…//};
上述例子中,一個參數被綁定到bool類型,而另一個參數仍未綁定需要由使用者指定。
補充一個指針的偏特化:
template <typename T>
class C {...}; //此泛化版本的T可以是任何類型
template <typename T>
class C<T*> {...}; //特化版本,T為指針類型
以上特點在STL裡面用的很多,有興趣參見我關于STL疊代器部分的博文。
2.函數模闆的“偏特化”
嚴格來說,函數模闆并不支援偏特化,但由于可以對函數進行重載,是以可以達到類似于類模闆偏特化的效果。
template <class T> void f(T); (a)
根據重載規則,對(a)進行重載
template < class T> void f(T*); (b)
如果将(a)稱為基模闆,那麼(b)稱為對基模闆(a)的重載,而非對(a)的偏特化。
四、模闆特化時的比對
1.類模闆的比對
最優化的優于次特化的,即模闆參數最精确比對的具有最高的優先權
例子:
template <class T> class vector{//…//}; // (a) 普通型
template <class T> class vector<T*>{//…//}; // (b) 對指針類型特化
template <> class vector <void*>{//…//}; // (c) 對void*進行特化
每個類型都可以用作普通型(a)的參數,但隻有指針類型才能用作(b)的參數,而隻有void*才能作為(c)的參數
2.函數模闆的比對
非模闆函數具有最高的優先權。如果不存在比對的非模闆函數的話,那麼最比對的和最特化的函數具有高優先權
例子:
template <class T> void f(T); // (d)
template <class T> void f(int, T, double); // (e)
template <class T> void f(T*); // (f)
template <> void f<int> (int) ; // (g)
void f(double); // (h)
bool b;
int i;
double d;
f(b); // 以 T = bool 調用 (d)
f(i,,d) // 以 T = int 調用(e)
f(&i) ; // 以 T = int* 調用(f)
f(d); // 調用(g)