模板特化
1.模板特化的定义
模板特化不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化。模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化。
template<> 返回值类型 函数名(形参列表){
//在函数体中可以使用类型参数
}
2.函数模板特化
函数模板特化是在一个统一的函数模板不能在所有类型实例下正常工作时,需要定义类型参数在实例化为特定类型时,函数模板的特定实现版本。
如下面的例子,如果不给出函数模板Max< T>在T为const char*时的特化版本,那么在比较两个字符串的大小时,比较的是字符串的起始地址的大小,而不是字符串的内容在字典序中先后次序。
#include <iostream>
using namespace std;
template<typename T> T Max(T t1,T t2){
return (t1>t2)?t1:t2;
}
typedef const char* CCP;
template<> CCP Max<CCP>(CCP s1,CCP s2){
return (strcmp(s1,s2)>0)?s1:s2;
}
int main(){
//调用实例:int Max<int>(int,int)
int i=Max(10,5);
//调用显示特化:const char* Max<const char*>(const char*,const char*)
const char* p=Max<const char*>("very","good");
cout<<"i:"<<i<<endl;
cout<<"p:"<<p<<endl;
}
程序正常编译运行结果:
i:10
p:very
使用函数重载替代函数模板特化
除了定义函数模板特化版本外,还可以直接给出模板函数在特定类型下的重载形式(普通函数)。使用函数重载可以实现函数模板特化的功能,也可以避免函数模板的特定实例的失效。例如,把上面的模板特化可以改成如下重载函数。
typedef const char* CCP;
CCP Max(CCP s1,CCP s2){
return (strcmp(s1,s2)>0)?s1:s2;
}
程序运行结果和使用函数模板特化相同。但是,使用普通函数重载和使用模板特化还是有不同之处,主要表现在如下两个方面:
(1)如果使用普通重载函数,那么不管是否发生实际的函数调用,都会在目标文件中生成该函数的二进制代码。而如果使用模板的特化版本,除非发生函数调用,否则不会在目标文件中包含特化模板函数的二进制代码。这符合函数模板的“惰性实例化”准则。
(2)如果使用普通重载函数,那么在分离编译模式下,应该在各个源文件中包含重载函数的申明,否则在某些源文件中就会使用模板函数,而不是重载函数。
3.类模板特化
类模板特化类似于函数模板的特化,即类模板参数在某种特定类型下的具体实现。
#include <iostream>
using namespace std;
template<typename T>class A{
T num;
public:
A(){
num=T(6.6);
}
void print(){
cout<<"A'num:"<<num<<endl;
}
};
template<>class A<char*>{
char* str;
public:
A(){
str="A' special definition ";
}
void print(){
cout<<str<<endl;
}
};
int main(){
A<int> a1; //显示模板实参的隐式实例化
a1.print();
A<char*> a2; //使用特化的类模板
A2.print();
}
程序输出结果如下:
A’num:6
A’ special definition