#include <iostream>
using namespace std;
template<typename T>
void func(T t) { std::cout << "matched template\n"; }
void func(long x) { std::cout << "matched long\n"; }
int main()
{
func(0);
}
输出:
matched template
在其他情况下,当重载分辨率可能不明确时,非模板函数是首选,为什么这个不同?
答案 0 :(得分:3)
§13.3.3[over.match.best] / p1-2:
1如下定义
ICSi(F)
:
- (1.1)[不适用的子弹省略]
- (1.2)let
ICSi(F)
表示隐式转换序列,它将列表中的第i个参数转换为第i个参数的类型 可行的功能F
。 13.3.3.1定义了隐式转换 序列和13.3.3.2定义了一个隐含的含义 转换序列是更好的转换序列或更糟 转换顺序比另一个。鉴于这些定义,可行函数
F1
被定义为a 如果适用于所有参数,则比另一个可行函数F2
具有更好的功能i
,ICSi(F1)
转换序列不比ICSi(F2)
差, 然后
(1.3)对于某些参数
j
,ICSj(F1)
是比ICSj(F2)
更好的转换序列,或者,如果没有,[省略了几个不适用的子弹]
- (1.6)
F1
不是函数模板特化,F2
是函数模板特化,或者,如果不是,- [不适用的子弹省略]
2如果只有一个可行的功能是更好的功能 比所有其他可行的功能,然后它是由选择的 超载分辨率;否则电话会形成不良。
§13.3.3.2[over.ics.rank],bullet 3.2:
- (3.2)标准转换序列
S1
是比标准转换序列S2
更好的转换序列
- (3.2.1)
S1
是S2
的正确子序列(比较13.3.3.1.1定义的规范形式的转换序列,不包括任何 左值变换;考虑身份转换序列 成为任何非身份转换序列的子序列)
让F1 = func<int>(int)
,F2 = func(long)
,只有一个类型为int
的参数。所以ICS1(F1)
是身份转换; ICS1(F2)
是从int
到long
的整数转换;因此ICS1(F1)
是一个比[{1}}每[over.ics.rank] /3.2.1更好的转换序列(因此根据定义并不比ICS1(F2)
差)。因此,根据[over.match.best]中的子弹1.3,F1优于F2。在子弹1.6中,模板/非模板决胜局根本就没有发挥作用。
答案 1 :(得分:0)
我认为(但不是绝对肯定,即不知道标准的确切引用,尽管会试图找到)如果参数与非模板的类型完全不匹配,那么模板将启动。或者,换句话说,转换的数量往往会最小化。例如,
f(long)
vs
template <typename T>
f(T)
f(long)
需要转换(从0
,例如int
到long
),而模板不需要转换(当然)。
经过@ T.C.的一些挖掘和帮助后,标准的相关部分是Sec。 13.3.3,[over.match.best]。这是一个相当长的技术部分,但基本上说使用Identity
转换的函数比非Identity
转换更受欢迎。
答案 2 :(得分:0)
隐式转换可能带来开销,对程序员来说可能是意外的,因此我认为标准选择不涉及转换的选项是合乎逻辑的。