模板設計的目的就是為了通用,但是某些情形下也有特殊情形獨立於通用規則,因此模板需要針對特殊情形進行特化。
1 類模板的特化,在模板類名自後<>內寫上特化的類型名,其中<>這部分叫做匹配式,如下:
template特化規則如下://通用模板 void show(); template<>//特化模板的模板參數,這裡不再需要參數故為空,<>不能省略 void show ();//特化模板,其中 叫匹配式
1) 匹配式寫在模板類名之後,用<>包住,即使模板特化沒有引入新的類型參數,<>也不能省略
2) 匹配式內用逗號隔開的項目列表,如前面的
3) 匹配式中各項目類型須與通用模板參數類型一致
4) 匹配式項目可以是具體的模板參數值,也可以是特化成具體的類型
5) 當匹配式項目是類型模板參數時,與函數變量類似,模板參數也可以用*、&、const、volatile等修飾
實例如下:
//用於模板型模板參數的模板 templatestruct S1; //模板通例,有三個模板參數,分別是類型參數,非類型參數及模板型參數 template class SP>//通用模板 struct S; //特例1,可匹配S template class SP> struct S ; //特例2,可匹配S<任意有const修飾的類型, 任意整數, S1> template class SP> struct S ; //特例3,完全特例,只能匹配S template<>//此例是完全特化,其余是部分特化 struct S ; //特例4,以模板實例作為類型參數值。匹配S , 10, S1> template struct S , 10, S1>; //特例5,錯誤!匹配式項目數與通例參數數不一致 // template class SP, typename TT> // struct S ; //特例6,錯誤!匹配式項目類型與通例參數類型不同 // template // struct S ; //特例7,錯誤!模板型參數SP與通例中SP類型不一致 // template class SP> // struct S ;
#includetemplate struct S { std::string id() {return "General";} }; //特例1,約束第三參數必須為char template struct S { std::string id() {return "Specialization #1";} }; //特例2,約束第二、第三參數必須均為char template struct S { std::string id() {return "Specialization #2";} }; //特例3,約束第一參數必須為int,且第二、第三參數相同 template struct S { std::string id() {return "Specialization #3";} }; int main() { using namespace std; cout << S ().id() << endl; //General cout << S ().id() << endl; //Specialization #3 cout << S ().id() << endl; //Specialization #1 cout << S ().id() << endl; //Specialization #2 //cout << S ().id() << endl; //可匹配2、3,有歧義 }
1) 最佳匹配原則,按照實參和形參的匹配程度最優選擇
2) 普通函數優先於模板實例
3) 模板實例間特化程度高的優先級高
實例如下:
#include程序輸出:using namespace std; template void fun(T x,N y){ cout<<"#1 "< void fun(T x,int y){ cout<<"#2 "< //函數模板不允許部分特化,只能完全特化 //void fun (T x,char y){ // cout<<"#3 "<<< void fun (char x,char y){//完全特化 cout<<"#4 "< void fun(double x,double y){ cout<<"#5 "< (1,2);//通用模板 fun (1,'a');//通用模板 fun<>('a','b');//指定了使用特化版本fun fun('a','b');//普通函數fun(char x,char y),當沒有這個普通函數時調用完全特化版本 fun(3.14,3.14156);//完全特化版本 fun(true);//普通函數fun(bool x) return 0; }
#1 1 2 #1 1 a #4 a b #7 a b #5 3.14 3.14156 #6 1
#include程序輸出:template void print() { print (); std::cout << i << std::endl; } //特例,終止遞歸。 template<> void print<1>() { std::cout << 1 << std::endl; } int main() { print<100>();//在編譯期展開相當於100條輸出語句 }
1
2
....
100