泛型設計之要點
C++11出來後,估計能好點,VS2010就引人了一些新特性,簡化了部分模板語法。
雖然模板在c++語法層面屬於二等公民,但是,從現在的趨勢來看,這幾年c++的主要改進點基本都集中在模板和模板相關的這塊,這塊也是C++和其他其他語言相抗衡的主要力量。
要分析STL,模板是基本的技術基礎,關於模板的基礎語法,這兒不談了,主要談下一些要點和難點
泛型設計之要點——模板推導順序
模板分函數模板和類模板,類模板支持偏特化(有點像高等數學中的偏導數),這是泛型編程的絕大多技術,技巧的根源。函數模板不支持偏特化,類似類模板偏特化的那些東西其實是函數重載。
(1)函數 模板的匹配規則
非模板函數具有最高的優先權。如果不存在匹配的非模板函數的話,那麼最匹配的和最特化的函數具有高優先權
- 普通非模板函數在參數匹配時如果和模板函數匹配度一樣好,優先選擇普通函數,因爲一等公民嘛
- 幾個主模板函數中選擇匹配最好的
- 如果2選擇不出,選擇“最特化”的,最特化的如果又對模板實參做了特話,這個會被選中
- 出現二義性
模板特化不參與重載推導
template<class T>
void f(T);
template<>
void f<int*>(int*)
template<class T>
void f(T*)
答案是 第三個
(2) 類模板的匹配規則
最優化的優於次特化的,即模板參數最精確匹配的具有最高的優先權
例子:
template <class T> class vector{//…//}; // (a) 普通型
template <class T> class vector<T*>{//…//}; // (b) 對指針類型特化
template <> class vector <void*>{//…//}; // (c) 對void*進行特化
每個類型都可以用作普通型(a)的參數,但只有指針類型才能用作(b)的參數,而只有void*才能作爲(c)的參數
泛型設計之要點——模板特化
模板有兩種特化,全特化和偏特化(局部特化)
模板函數只能全特化,沒有偏特化(以後可能有)。
模板類是可以全特化和偏特化的。
全特化,就是模板中模板參數全被指定爲確定的類型。
全特化也就是定義了一個全新的類型,全特化的類中的函數可以與模板類不一樣。
偏特化,就是模板中的模板參數沒有被全部確定,需要編譯器在編譯時進行確定。
在泛型中,利用特化類得到類新的特性,以便找到最適合這種特性的實現。而這一切都是在編譯時完成。
模板的特化是非常有用的。它像一個在編譯期的條件判斷。當編譯器在編譯時找到了符合的特化實現,就會使用這個特化實現。這就叫編譯器多態(或者叫靜態多態)。這種東西對編寫基礎庫是很有用的。這也就是爲何c++的基礎庫大量使用了模板技術,而且大量使用了特化,特別是偏特化。