1.函数可以和类一样定义为模板函数。
模板函数与模板类最大的不同是:模板函数可以通过函数的参数确定模板类型。
template<class T,int i> T&lookup(string<T> &s,const int n){......}
string<float> s;
int x=0;
lookup(s,x);//这里自动识别到T就是float
类模板不会对参数进行推断的原因是一个类可以提供多个构造函数,在某些时候对模板类的参数进行推断是无法完成的。
当模板函数无法通过参数推断它的类型时,需要程序员显示描述:
template<class T> T *function(){......}
void f()
{
int*p=function<int>( ); //需要显示的描述出模板类型
}
显示描述最常见的情况就是为模板函数提供返回值的类型。
2.模板函数的重载
模板函数和普通的函数一样,可以声明多个具有同样名字的函数模板,甚至可以声明多个具有同一个名字的多个函数模板和常规函数的组合。
进行函数重载时,会按照重载解析去找出最佳匹配,找不到匹配或者出现两个以上的匹配就会报错。会优先选择常规函数。
template<class T> T sqrt(T);
templete<class T> complex<T> sqrt(complex<T>);
double sqrt(double);
void f (complex<double>z)
{
sqrt(2);//sqrt<int>(int)
sqrt(2.0);//sqrt(double);优选选择匹配的常规函数,常规函数是能够同时匹配的模板函数的子集。
sqrt(z);//sqrt<double>(complex<double>);complex<T> sqrt(complex<T>)是T sqrt(T)的子集,子集意味着更针对,所以选择子集。
}
——————————————————————————————————————————————————————————
tmplate<class T> T max(T,T);
max(1, 2);//max<int>(int,int)
max('a', 'b');//max<char>(char,char)
max(1.3, 1);//错误,直觉会选择提升int为浮点类型。但是这里在重载解析时已经发生了歧义。也不存在一种标准转换如子类指针值赋给基类指针。
max<double>(2.1, 5);//不存在重载解析的歧义,故和常规函数一样发生了隐式转换。
———————————————————————————————————————————————————————————
tmeplate<class T> T get(T&p,int n);//对p发生参数类型推断,不能进行隐式类型转换。对第二个参数n,所有可能的转换都需要考虑。
——————————————————————————————————————————————————————————
函数模板大可看作一种编译辅助完成重复性声明的技术,它能减少部分重复性的工作,提升效率,而且在代码可读性上有所提升。