模板设计的目的就是为了通用,但是某些情形下也有特殊情形独立于通用规则,因此模板需要针对特殊情形进行特化。
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 ;
2 类模板匹配按照最佳匹配原则进行匹配,实例如下:
#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,有歧义 }
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
4 模板特化用于编译期条件判断,实例如下:
#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