于函数模板,编译器用实参来推断模板参数
这个过程成为模板实参推断
类型转换与模板类型参数
一般而言,不会转化实参以匹配已有的实例化,相反,会产生新的实例化,或产生不了实例化,报错。
只有两个例外:
const转换:
- 如果模板形参为const引用,则其可以接受const或非const引用
- 如果模板形参为const指针,则其可以接受const或非const指针
- 如果模板形参不是引用或指针 (值传递),则形参和实参都忽略const
数组或函数到指针的转换
- 如果模板形参不是引用或指针(值传递),则数组会转化为指针,数组实参将当作指向其第一个元素的指针;
- 如果模板形参不是引用或指针(值传递),则函数会转化为指针,函数实参将当作指向函数类型的指针;
1 | template <typename T> T fobj(T, T);//值传递 |
函数模板显式实参
定义一个模板1
2template<typename T1, typename T2>
T1 sum(T1 s);
从这个函数实参我们仅仅可以推断出T2的类型
因此,为了推断出T1,必须为显式指定这两个类型1
auto val2=sum<int, long>(i);
尾指返回类型与类型转换
当你遇到这种情况1
2
3
4template<typename T>
??? &fcn(T beg, T end) {
return *beg;
}
这时,你无法确定返回值是什么,
你知道的只有接收一对迭代器和要返回一个元素的引用
这时你就需要decltype
1
2
3
4template<typename T>
auto fcn(T beg, T end)->decltype(*beg) {
return *beg;
}
要是你想返回的不是引用而是一个值
那么,你需要remove_reference::type
1
2
3
4
5template<typename T>
auto fcn(T beg, T end)->
typename remove_reference<decltype(*beg)>::type {
return *beg;
}
根据指针类型来推断模板实参
1 | template <typename T> |
此时,T=int
;1
2
3
4
5template <typename T>
T compare(const T&, const T&);
void func(int(*)(const int&, const int&));
void func(string(*)(const string&, const string&));
func(compare);//error
因为无法判断使用compare的哪一个版本
想要成功调用,只能显式声明1
func(compare<int>);