#include
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 s1,CCP s2){
return
(
strcmp
(s1,s2)>0)?s1:s2;
}
int
main(){
//调用实例:int Max(int,int)
int
i=Max(10,5);
//调用显示特化:const char* Max(const char*,const char*)
const
char
* p=Max<
const
char
*>(
"very"
,
"good"
);
cout<<
"i:"
<
cout<<
"p:"
<}
程序正常编译运行结果: i:10p:very在函数模板显示特化定义(Explicit Specialization Definition)中,显示关键字template和一对尖括号<>,然后是函数模板特化的定义。该定义指出了模板名、被用来特化模板的模板实参,以及函数参数表和函数体。在上面的程序中,如果不给出函数模板Max在T为const char*时的特化版本,那么在比较两个字符串的大小时,比较的是字符串的起始地址的大小,而不是字符串的内容在字典序中先后次序。1.1.1使用函数重载替代函数模板特化除了定义函数模板特化版本外,还可以直接给出模板函数在特定类型下的重载形式(普通函数)。使用函数重载可以实现函数模板特化的功能,也可以避免函数模板的特定实例的失效。例如,把上面的模板特化可以改成如下重载函数:1234typedef
const
char
* CCP;
CCP Max(CCP s1,CCP s2){
return
(
strcmp
(s1,s2)>0)?s1:s2;
}
程序运行结果和使用函数模板特化相同。但是,使用普通函数重载和使用模板特化还是有不同之处,主要表现在如下两个方面:(1)如果使用普通重载函数,那么不管是否发生实际的函数调用,都会在目标文件中生成该函数的二进制代码。而如果使用模板的特化版本,除非发生函数调用,否则不会在目标文件中包含特化模板函数的二进制代码。这符合函数模板的“惰性实例化”准则。(2)如果使用普通重载函数,那么在分离编译模式下,应该在各个源文件中包含重载函数的申明,否则在某些原文件中就会使用模板实例化,而不是重载函数。1.3类模板特化
类模板特化类似于函数模板的特化,即类模板参数在某种特定类型下的具体实现。考察如下代码:12345678910111213141516171819202122232425262728293031#include
using
namespace
std;
template
<
typename
T>
class
A{
T num;
public
:
A(){
num=T(6.6);
}
void
print(){
cout<<
"A'num:"
<
}
};
template
<>
class
A<
char
*>{
char
* str;
public
:
A(){
str=
"A' special definition "
;
}
void
print(){
cout<
}
};
int
main(){
A<
int
> a1;
//显示模板实参的隐式实例化
a1.print();
A<
char
*> a2;
//使用特化的类模板
A2.print();
}
程序输出结果如下:A'num:6A' special definition“I find that the harder i work,the more luck i seem to have!”