Why f(1, 2, 3);
调用#2?
您的问题中有很多问题(请每个问题一个问题!),所以我会坚持这一个问题。首先,我们进行模板推导。 #3 失败,但 #1 和 #2 成功:
template<class... Args>
void f(Args... args); // #1, with Args = {int, int, int}
template<class T1, class... Args>
void f(T1 a1, Args... args); // #2, with T1 = int, Args = {int, int}
这两个函数都需要三个int
s 按值,因此重载决策中的所有正常决胜局都无法解决歧义。所以我们到了最后一个:
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
— [...]
— F1
and F2
are function template specializations, and the function template for F1
is more specialized
than the template for F2
according to the partial ordering rules described in 14.5.6.2.
规则是:
Step 1:合成类型[temp.func.order]:
为每个类型、非类型或模板模板参数(包括
模板参数包(其中的14.5.3))分别合成唯一的类型、值或类模板
并将其替换为模板函数类型中该参数的每次出现。
所以我们有:
void f(Pack1... args); // #1
void f(U2 a1, Pack2... args); // #2
Step 2:按照[temp.deduct.partial]中的描述执行扣除。我们所处的上下文是函数调用,因此我们使用函数调用具有参数的类型。
首先,我们尝试从#1 推导出#2。也就是说,我们尝试匹配 (T1, Args...
) 反对(Pack1...)
。第一部分是P = T1, A = Pack1...
。我们有:
如果 A 是从函数参数包转换而来并且 P 不是参数包,则类型推导失败。
所以从 #1 推导出 #2 失败,所以论证Args...
至少不像T1, Args...
.
接下来,我们尝试从#2 中推导出#1。也就是说,我们尝试匹配(Args...)
反对(U2, Pack2...)
。这样就成功了,所以T1, Args...
至少与Args...
.
由于#2 至少与#1 一样专业,而#1 至少不如#2 专业,因此我们可以说#2 更专业:
功能模板F
至少与函数模板一样专业G
如果,对于每对类型用于
确定排序、类型F
至少与来自的类型一样专业G
. F
更专业
比G
if F
至少与G
and G
至少不像F
.
更专业的模板是首选,所以我们称之为#2。