1 函数模板的定义
template<类型参数表>
返回值 函数名(数据参数表)
{
函数模板定义体;
}
例如
template <typename T>
T& mymax(T& a, T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;/*打印方法名*/
return (a<b)? b : a;
}
2 函数模板的使用
1. 函数模板只是编译指令,一般写在头文件中;
2. 编译程序时,编译器根据函数的参数来“推导”模板的参数;然后生成具体的模板函数
示例代码:
int a;int b;mymax(a,b);
编译器根据函数参数a,b推导模板参数为int,所以把模板中的T绑定为int;
编译程序时生成如下函数:
int& mymax(int& a,int& b)
{
return (a<b)? b : a;
}
3 模板函数推导时的注意事项
3.1 有限的类型转换
3.1.1函数模板只支持2中隐式类型转换
3.1.1.1 const转换
template <typename T>
const T& mymax(const T& a, const T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a<b)? b : a;
}
int main(int argc, char **argv)
{
int ia = 1,ib = 2;
double da = 1,db = 2;
mymax(ia, ib);
mymax(db, db);
return 0;
}
输出
const T &mymax(const T &, const T &) [T = int]
const T &mymax(const T &, const T &) [T = double]
3.1.1.1 数组或指针转换数组
数组调用引用时,引用为数组类型
如char a[] = "abc"; 引用为char[4];
template <typename T>
const T& mymax(const T& a, const T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a<b)? b : a;
}
main()
{
char a[] = "abc";
char b[] = "ab";
mymax(a,b);//报错,引用类型不同,无法推导方法;
}
采用数组指针时可以
template <typename T>//每定义一个模板函数都要写一个。及时其他模板写了也要写。
const T* mymax2(const T* a, const T* b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a<b)? b : a;
}
mymax2(a,b);//ok,编译通过
这里调用函数指针也是可以,不过输入的两个函数指针的返回值和参数要一样
3.1.2 其他的隐式转换都不支持,比如:算术转换、派生类对象向上转换
3.2 苛刻的类型匹配
参数类型必须完全匹配:
如果不能直接匹配,则可以进行“有限的类型转换”,如果还不匹配,则推导失败
3.3
参数类型为传值时
忽略实参的const,volatile等属性,因为传值时,会临时生成一个变量,次变量可读可写
3.4 可在函数模板中打印匹配结果
cout<<__PRETTY_FUNCTION__<<endl;
4 模板函数重载
重载,即有多个同函数名和返回值得函数,那应该选择调用哪个函数呢
1 先列出候选函数,包括普通函数,参数推导成功的模板函数
2 这些获选函数,根据“类型转换”来排序(注意,模板函数只支持有限的类型转换)
3 如果某个候选函数的参数,跟调用时传入的参数更加匹配,则选择此候选函数
4 如果这些候选函数的参数匹配度相同:1 如果只有一个非模板函数,则选择它;2如果只有模板函数,则选择"则更特化"的模板函数;3否则,最后导致“二义性”错误(ambiguous 模糊)
网友评论