一般来说,由函数调用参数推导模板参数是函数模板调用的关键。也就是,调用参数类型隐含着模板参数类型,如果能够推导出模板参数,那么就不需要显示指定。
//EXP1:
template <typename T>
const T& Max(const T& a,const T& b)
{
return a>b?a:b;
}
Max(3,5);//函数实参3和5都是int类型,我们可以很容易推导出T=int。
那什么时候指定模板函数的实参类型呢?
1、当调用产生歧义的时候,可以指定实参类型。
Max<int>(3.0,5);//因为我们定义的函数模板只有类型T,函数参数是相同的,在用实参double的3.0和int的5调用就找不到匹配的函数,所以必须显示<类型>
当然我们还可以通过Max(static_cast(3.0),5)和重载函数模板方式解决这种歧义,不过我觉得这种方式最理想!
2、调用参数与模板参数没发生关联。返回类型为模板类型,且与模板参数类型不一致时,就是这种情况下的一个典型例子。
//EXP2:
template <typename RT,typename T1,typename T2>
const RT& Max(const T1& a,const T2& b)
{
return a>b?a:b;
}
Max<int,double,int>(3.0,5);//全部指定实参类型,顺序不能变
Max<int>(3.0,5); //这是一种简写方式,这种要求最后一个不能被隐式推导的模板实参之前的所有实参类型都要指定
//在这里,3.0推导出T1为double类型,5推导出T2为int类型,RT是不能被推导的,所以要显示指定
3、存在重载函数情况下,在函数名称后面加个空<>,表示只调用模板函数,且模板参数是通过调用参数推导出来的
Max<>(3,5);