为什么模板重载比简单转换更匹配?

Why is template overload a better match than a simple conversion?

#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

在其他情况下,当重载解析可能不明确时,首选非模板函数,为什么这个不同?

我认为(但不是绝对确定,即不知道标准中的确切引用,但会尝试查找)如果参数与非模板的类型不完全匹配,那么模板将启动。或者,换句话说,转换次数趋于最小化。例如,在

f(long)

对比

template <typename T>
f(T)

f(long) 需要转换(从 0,例如 int,到 long),而模板不需要(当然)转换。

经过@T.C 的一些挖掘和帮助,标准的相关部分是 Sec。 13.3.3,[over.match.best]。这是一个相当长的技术部分,但基本上是说带有 Identity 转换的函数优于非 Identity 转换。

隐式转换可能会带来开销,并且可能对程序员来说是意想不到的,所以对我来说,标准选择不涉及转换的选项似乎是合乎逻辑的。

§13.3.3 [over.match.best]/p1-2:

1 Define ICSi(F) as follows:

  • (1.1) [inapplicable bullet omitted]
  • (1.2) let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

  • (1.3) for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

  • [several inapplicable bullets omitted]

  • (1.6) F1 is not a function template specialization and F2 is a function template specialization, or, if not that,
  • [inapplicable bullet omitted]

2 If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed.

§13.3.3.2 [over.ics.rank],项目符号 3.2:

  • (3.2) Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
    • (3.2.1) S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence)

令 F1 = func<int>(int),F2 = func(long),只有一个参数,类型为 int。所以ICS1(F1)就是身份转换; ICS1(F2)是从intlong的整数转换;因此,根据 [over.ics.rank]/3.2.1 ICS1(F1) 是比 ICS1(F2) 更好的转换序列(因此根据定义并不比 ICS1(F2) 差)。因此,根据 [over.match.best] 中的项目符号 1.3,F1 优于 F2。 template/non-template 决胜局,在项目符号 1.6 中,根本没有发挥作用。