【问题标题】:overload resolution between lvalue reference and rvalue reference左值引用和右值引用之间的重载决议
【发布时间】:2017-09-08 12:06:11
【问题描述】:
#include <iostream>

using namespace std;

void func(int (&ref)[6]) { cout << "#1" << endl; }
void func(int * &&ref) { cout << "#2" << endl; }

int main()
{
  int arr[6];
  func(arr); // g++(5.4): ambiguous, clang++(3.8): #2, vc++(19.11): #1

  return 0;
}

这两个函数都是完全匹配的。以下是标准的引用:

标准转换序列 S1 是比标准转换序列更好的转换序列 标准转换序列S2 if

...

S1 和 S2 是引用绑定 (8.5.3),两者都没有引用 声明的非静态成员函数的隐式对象参数 没有 ref 限定符,并且 S1 将右值引用绑定到右值 S2 绑定一个左值引用。

不是说第二个更好吗?

更新:

There 是一个相关问题。而下面的代码就是它的简化版。

#include <iostream>

using namespace std;

void func(int *&) { cout << "#1" << endl; }
void func(int *&&) { cout << "#2" << endl; }

int main()
{
  int arr[6];
  func(arr);  // g++(5.4) and clang++(3.8): #2, vc++(19.11): ambiguous

  return 0;
}

【问题讨论】:

  • “更好”是什么意思?
  • Fwiw,这个succeeds with clang
  • 这会打开 int (&amp;ref)[6] 是否是“左值引用”,正如引用中所引用的那样。尽管这是一个引用,但可以说这不是对左值的引用。如果是,您可以分配给ref,即ref=&lt;something&gt;。但你不能。
  • 直到从数组到指针衰减创建的指针是prvalue(我想回想起来并不奇怪)
  • @SamVarshavchik 为什么,当然是这样。 8.3.2 [dcl.ref] "使用&amp; 声明的引用类型称为左值引用"。

标签: c++ overloading language-lawyer rvalue-reference


【解决方案1】:

我认为这取决于特定短语的含义。

两种转换是等价的,因为我们排除了lvalue transformations(基本上,数组实际上是一个指针,所以它不算作转换),所以我们进入你在[over.ics.rank]中指出的下一个决胜局:

S1 和 S2 是引用绑定,两者都不是引用非静态成员函数的隐式对象参数,声明时没有引用限定符,S1 将右值引用绑定到右值,S2 绑定左值引用

这种情况适用吗?我们确实有两个引用绑定:

int arr[6];
int (&a)[6] = arr;  // #1
int *&& b = arr;    // #2

这里,#1 绑定一个左值引用。 #2 属于[dcl.init.ref]:

否则,初始化表达式被隐式转换为“cv1 T1”类型的纯右值。应用临时实现转换并将引用绑定到结果。

arr 隐式转换为int* 类型的纯右值,然后绑定到b


所以现在的问题是 - [over.ics.rank] 中的限制是什么意思?这可能意味着:

  • 通常绑定到右值的右值引用。这显然是clang的解释。右值引用绑定到从arr 的右值转换中实现的临时物化。
  • 具体来说,参数表达式是一个右值,它绑定到右值引用参数。这显然是 gcc 的解释,并且由于 arr 不是右值(它是左值),因此将跳过此决胜局并且不会应用后续的决胜局。

我倾向于在这里实现 gcc。否则,“将右值引用绑定到右值”这句话的意义何在?右值引用不能绑定到左值。这是多余的。也就是说,对于这种解释,它的措辞也很尴尬。

照原样,我将其称为措辞错误。

【讨论】:

  • 对于编译器来说,如果某些东西不符合标准,有适当的网页可以分享挫败感......有没有办法在标准缺陷的情况下提交报告?
  • +1,也倾向于支持 gcc 的实现。我想补充一点,[over.ics.rank] 下面提供的代码示例严格处理将右值绑定到右值引用,并且唯一的左值绑定到左值引用。
  • 嗯,我将其读作“S1 将右值引用绑定到右值,S2 将左值引用绑定到 [右值]”,为简洁起见省略了重复。
  • @T.C.我什至从未想过这个措辞。这确实更有意义。我认为值得建议进行编辑编辑,将其更改为“S1 绑定右值引用,S2 将左值引用绑定到右值”?还有,那么clang怎么调用#2呢?
猜你喜欢
  • 2017-03-26
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 2021-11-30
相关资源
最近更新 更多