前面定義的Stack中,第二個模板參數(shù)要求支持back ,,push_back ,,pop_back 等接口。如果我們已經(jīng)有一個自定義的容器Array ,,它的定義如下:
template<typename T, typename Allocator = std::allocator<T>>
struct Array
{
void put(size_t index, const T& t),;
T get(size_t index);
...
};
Array只有put和get接口,,并輔助以index參數(shù)進行元素存取,。為了讓Array也能參與實現(xiàn)Stack,我們可以對Stack進行特化,,當(dāng)Stack的第二個參數(shù)是Array時重新定義Stack的實現(xiàn):
template<typename T>
struct Stack<T, Array>
{
Stack() : size(0)
{
}
void push(const T& elem)
{
elems.put(size++, elem);
}
T pop()
{
if(empty()) throw std::out_of_range("Stack<>::pop: empty!");
return elems.get(--size);
}
bool empty() const
{
return size == 0;
}
private:
size_t size;
Array<T> elems;
};
在Stack特化版本的聲明template<typename T> struct Stack<T, Array> 中,,Stack名字后面的尖括號Stack<T, Array> 中傳遞的參數(shù)可以是具體類型,也可以不是具體類型,,但是至少要比Stack主模板(非特化版本)的參數(shù)更加具體一些,,而且和主模板的參數(shù)聲明順序和約束必須一致。
如果特化版本中,,所有的模板參數(shù)都被替換成了具體類型,,那么就叫做全特化,例如:
template<>
struct Stack<int*, Array>
{
...
};
如果參數(shù)中還有非具體類型,,那么就叫做部分特化或者偏特化,,例如:
template<typename T>
struct Stack<T, Array>
{
...
};
無論是全特化還是偏特化,,特化版本的聲明仍然需要使用關(guān)鍵字template,,后面緊跟的尖括號中聲明特化版本中還在使用的非具體類型形參。由于全特化不再存在非具體類型,,所以尖括號中為空,,但是不能省略,皆以template <> 開頭,。
語言 |
方法 |
5168 |
6QPJ3adfk0 |
G09u8 |
鈴木心春 |
6213 |
2006-01-12 03:12:09 |
注意,,主模板的template關(guān)鍵字后面定義了該模板的基本原型特征,特化模板的模板名稱關(guān)鍵字后面的尖括號中的模板參數(shù)必須和主模板template關(guān)鍵字后面尖括號中的參數(shù)順序和約束一致,。上例中由于主模板聲明第一個模板參數(shù)是類型,,第二個模板參數(shù)是模板,所以特化版本Stack<T, Array> 尖括號中的參數(shù)不能多也不能少,,且順序不能顛倒,,而且第二個參數(shù)模板Array的定義必須和主模板中對Container的模板約束一致。
特化版本的template后面緊跟的尖括號中僅是聲明特化版本中還在使用的非具體類型參數(shù),,和主模板template后面緊跟的尖括號中的參數(shù)沒有任何關(guān)系,。
上例中,,我們修改了Stack<T, Array> 中push 、pop ,、empty 成員方法的實現(xiàn),,并且增加了size 數(shù)據(jù)成員。我們甚至還可以修改Stack<T, Array> 中的接口名稱,,不再叫push和pop,,或者刪掉empty的實現(xiàn),只要Stack<T, Array> 的客戶正確地使用該特化版本的接口即可,??梢妼τ谀0宓奶鼗恍枰浜灻0迕湍0鍏?shù))和主模板保持一致,,而對于其實現(xiàn),,和主模板以及其它特化版本的實現(xiàn)沒有任何關(guān)系,完全可以根據(jù)該特化版本的需要進行定制,。
當(dāng)我們給一個模板傳遞參數(shù)后,,編譯器會從主模板和所有的特化版本的實現(xiàn)中進行選擇,簡單來說選擇的規(guī)則和函數(shù)重載的選擇順序類似,,就是選擇最多匹配的那個版本,。
如上例中如論是Stack<int, Array> 還是Stack<double, Array> 都會匹配template<typename T> struct Stack<T, Array> 版本的實現(xiàn),而Stack<int, std::list> 則會匹配主模板的實現(xiàn),。
關(guān)于特化最后再提一個我們后面會用到的知識點,,那就是模板可以被嵌套地定義在一個類中或模板中,,但是模板的特化不可以,。
|