前面定義的stack中,第二個模板引數要求支援back
,push_back
,pop_back
等介面。如果我們已經有乙個自定義的容器array
,它的定義如下:
template>
struct array
;
array只有put和get介面,並輔助以index引數進行元素訪問。為了讓array也能參與實現stack,我們可以對stack進行特化,當stack的第二個引數是array時重新定義stack的實現:
template
struct stack, array>
void push(const t& elem)
t pop()
bool empty() const
private:
size_t size;
array> elems;
};
在stack特化版本的宣告templatestruct stack
中,stack名字後面的尖括號stack
中傳遞的引數可以是具體型別,也可以不是具體型別,但是至少要比stack主模板(非特化版本)的引數更加具體一些,而且和主模板的引數宣告順序和約束必須一致。
如果特化版本中,所有的模板引數都被替換成了具體型別,那麼就叫做全特化,例如:
template<>
struct stack
;
如果引數中還有非具體型別,那麼就叫做部分特化或者偏特化,例如:
template
struct stack, array>
;
無論是全特化還是偏特化,特化版本的宣告仍然需要使用關鍵字template,後面緊跟的尖括號中宣告特化版本中還在使用的非具體型別形參。由於全特化不再存在非具體型別,所以尖括號中為空,但是不能省略,皆以template <>
開頭。
注意,主模板的template關鍵字後面定義了該模板的基本原型特徵,特化模板的模板名稱關鍵字後面的尖括號中的模板引數必須和主模板template關鍵字後面尖括號中的引數順序和約束一致。上例中由於主模板宣告第乙個模板引數是型別,第二個模板引數是模板,所以特化版本stack
尖括號中的引數不能多也不能少,且順序不能顛倒,而且第二個引數模板array的定義必須和主模板中對container的模板約束一致。
特化版本的template後面緊跟的尖括號中僅是宣告特化版本中還在使用的非具體型別引數,和主模板template後面緊跟的尖括號中的引數沒有任何關係。
上例中,我們修改了stack
中push
、pop
、empty
成員方法的實現,並且增加了size
資料成員。我們甚至還可以修改stack
中的介面名稱,不再叫push和pop,或者刪掉empty的實現,只要stack
的客戶正確地使用該特化版本的介面即可。可見對於模板的特化,只需要其簽名(模板名和模板引數)和主模板保持一致,而對於其實現,和主模板以及其它特化版本的實現沒有任何關係,完全可以根據該特化版本的需要進行定製。
當我們給乙個模板傳遞引數後,編譯器會從主模板和所有的特化版本的實現中進行選擇,簡單來說選擇的規則和函式過載的選擇順序類似,就是選擇最多匹配的那個版本。
如上例中如論是stack
還是stack
都會匹配templatestruct stack
版本的實現,而stack
則會匹配主模板的實現。
關於特化最後再提乙個我們後面會用到的知識點,那就是模板可以被巢狀地定義在乙個類中或模板中,但是模板的特化不可以。
C 11 模板的改進
在c 98 03的泛型程式設計中,模板例項化有乙個很繁瑣的地方,就是連續兩個右尖括號 會被編譯解釋成右移操作符,而不是模板參數列的形式,需要乙個空格進行分割,以避免發生編譯時的錯誤。template class x template class y int main 在例項化模板時會出現連續兩個右尖...
C 模板 模板特化 模板偏特化
模板是c 的乙個重要特性 使用模板 可以極大的減少類似功能 的編寫 這可以看做是c 相較於c的進步 因為這一特性在c中是不容易達到的 語言層面不支援 模板的關鍵字是 template 簡單的模板應用 template class test int main 使用模板的類在例項化時需要指明模板引數型別...
C 模板特化 偏特化
注意 特化時模板引數的先後順序不能變 特化是基於泛化版本進行的 函式模板特化過載與函式過載不衝突 函式模板只能全特化不能偏特化 模板類泛化 templateclass mytest int m func 模板類全特化 template class mytest 模板類偏特化 templateclas...