【问题标题】:Why is an lvalue-ref overload unambiguously chosen over a forwarding-ref overload for an lvalue?为什么要明确选择左值引用重载而不是左值的转发引用重载?
【发布时间】: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

这似乎是一种正确的行为,但我不明白为什么会发生(实际上我的代码不是我所期望的)。

来自Overload resolution

如果任何候选者是函数模板,则其特化是使用模板参数推导生成的,并且此类特化被视为与非模板函数一样,除非在决胜局规则中另有规定。

好的,让我们生成专业化。对于#1 来说很简单,它变成了int foo(int&amp; x)。对于 #2 特殊扣除规则适用,因为它是转发参考。 i 是一个左值,因此T 被推导出为int&amp;T&amp;&amp; 变为int&amp; &amp;&amp;,在引用折叠后变为int&amp;,产生结果int foo(int&amp; x)。这与 #1 完全相同!

所以我希望看到一个模棱两可的电话,但这不会发生。谁能解释一下为什么?在这里使用什么决胜局来选择最佳可行功能?

另见related discussion in Slack,有一些想法。

【问题讨论】:

  • 我最终删除了我的答案,因为我很难解释规范这一点的标准部分。几乎第 2 到第 4 段 here 涵盖了这个
  • 我认为这里的重点是“除非在决胜局规则中另有规定”包括“它说更专业的模板比不那么专业的模板更受欢迎”,并且仅#1接受左值引用比接受转发引用的#2 更专业。
  • 过程是“函数模板的部分排序”。它由this 部分和this 部分覆盖。两者都非常适合弄清楚算法。但是有一个decent post 详细介绍了整个过程,这可能有助于阐明它是如何工作的。
  • 至于这个的情况。如果要在这里执行订购,他们最终将不得不申请this bullet。这基本上使左值引用在排名中略有优势,因此在选择左值重载方面起着关键作用。

标签: c++ templates overloading forwarding-reference


【解决方案1】:

非语言律师的回答是,对于这种情况,有一个决胜局规则。

充分理解标准措辞以解码它需要一个简短的书章。但是,当推导出 T&amp;&amp;T&amp; 重载是在左值和其他所有关系之间选择的选项时,T&amp; 获胜。

这样做是为了 (a) 使通用引用起作用,而 (b) 如果您想单独处理左值引用,则允许您重载左值引用。

决胜局来自模板函数重载“更专业”的排序规则。与T* 优于T 的原因相同,即使T=Foo*T=Foo 都提供相同的函数参数。模板参数发生了二次排序,T 可以模拟T* 意味着T* 的事实更加专业(或者说不是,标准中的措辞很尴尬)。一条额外的规则说明T&amp; 优于 T&amp;&amp; 的左值在同一部分中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2015-06-01
    • 1970-01-01
    • 2021-12-25
    • 2017-05-09
    • 2017-03-26
    相关资源
    最近更新 更多