【发布时间】:2021-11-28 17:43:05
【问题描述】:
看看这两个重载的函数模板:
template <class T>
int foo(T& x) { // #1
return 1;
}
template <class T>
int foo(T&& x) { // #2
return 2;
}
我通过以下方式致电foo:
int i;
foo(i); // calls #1
并且明确选择了重载 #1:https://gcc.godbolt.org/z/zchK1zxMW
这似乎是一种正确的行为,但我不明白为什么会发生(实际上我的代码不是我所期望的)。
如果任何候选者是函数模板,则其特化是使用模板参数推导生成的,并且此类特化被视为与非模板函数一样,除非在决胜局规则中另有规定。
好的,让我们生成专业化。对于#1 来说很简单,它变成了int foo(int& x)。对于 #2 特殊扣除规则适用,因为它是转发参考。 i 是一个左值,因此T 被推导出为int& 和T&& 变为int& &&,在引用折叠后变为int&,产生结果int foo(int& x)。这与 #1 完全相同!
所以我希望看到一个模棱两可的电话,但这不会发生。谁能解释一下为什么?在这里使用什么决胜局来选择最佳可行功能?
另见related discussion in Slack,有一些想法。
【问题讨论】:
-
我最终删除了我的答案,因为我很难解释规范这一点的标准部分。几乎第 2 到第 4 段 here 涵盖了这个
-
我认为这里的重点是“除非在决胜局规则中另有规定”包括“它说更专业的模板比不那么专业的模板更受欢迎”,并且仅#1接受左值引用比接受转发引用的#2 更专业。
-
过程是“函数模板的部分排序”。它由this 部分和this 部分覆盖。两者都非常适合弄清楚算法。但是有一个decent post 详细介绍了整个过程,这可能有助于阐明它是如何工作的。
-
至于这个的情况。如果要在这里执行订购,他们最终将不得不申请this bullet。这基本上使左值引用在排名中略有优势,因此在选择左值重载方面起着关键作用。
标签: c++ templates overloading forwarding-reference