模板是C++中一個很重要的特性,寫一份代碼能用於多種數據類型(包括用戶自定義類型)。例如,STL的sort()函數可以用於多種數據類型的排序,類stack可以用作多種數據類型的棧。但是,如果我們想對特定的數據類型執行不同的代碼(而不是通用模板)呢?這種情況下就可以使用模板特例化(template specialization)。
一、函數模板特例化
當特例化一個函數模板時,必須為原模板中的每個模板參數都提供實參。使用關鍵字template后跟一個空尖括號<>,即template <>,以指出我們正在特例化一個模板。
template <typename T>
void fun(T a)
{
cout << "The main template fun(): " << a << endl;
}
template <> // 對int型特例化
void fun(int a)
{
cout << "Specialized template for int type: " << a << endl;
}
int main()
{
fun<char>('a');
fun<int>(10);
fun<float>(9.15);
return 0;
}
輸出結果:
The main template fun(): a Specialized template for int type: 10 The main template fun(): 9.15
對於除int型外的其他數據類型,都會調用通用版本的函數模板fun(T a);對於int型,則會調用特例化版本的fun(int a)。注意,一個特例化版本的本質是一個實例,而非函數的重載。因此,特例化不影響函數匹配。
二、類模板特例化
除了特例化函數模板,我們還可以特例化類模板。下面是一個簡單的例子:
template <typename T>
class Test{
public:
void print(){
cout << "General template object" << endl;
}
};
template<> // 對int型特例化
class Test<int>{
public:
void print(){
cout << "Specialized template object" << endl;
}
};
int main()
{
Test<int> a;
Test<char> b;
Test<float> c;
a.print();
b.print();
c.print();
return 0;
}
輸出結果:
Specialized template object General template object General template object另外,與函數模板不同,類模板的特例化不必為所有模板參數提供實參。我們可以只指定一部分而非所有模板參數,這種叫做類模板的 偏特化 或 部分特例化(partial specialization)。例如,C++標准庫中的類vector的定義:
template <typename T, typename Allocator>
class vector
{
/*......*/
};
// 部分特例化
template <typename Allocator>
class vector<bool, Allocator>
{
/*......*/
};在vector這個例子中,
一個參數被綁定到bool類型,而另一個參數仍未綁定需要由用戶指定。注意,一個類模板的部分特例化版本仍然是一個
模板,因為使用它時用戶還必須為那些在特例化版本中未指定的模板參數提供實參。
