左值参考和右值参考之间的重载分辨率

时间:2017-09-08 12:06:12

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

#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,如果

     

...

     

S1和S2是参考绑定(8.5.3),都不是指   声明的非静态成员函数的隐式对象参数   没有ref-qualifier,S1将rvalue引用绑定到rvalue   和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;
}

1 个答案:

答案 0 :(得分:3)

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

两次转换都是等效的,因为我们排除lvalue transformations(基本上,数组实际上是一个指针,因此它不算作转换),所以我们进入你在{{3中指出的下一个决胜局}}:

  

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

这种情况适用吗?我们有两个参考绑定:

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

这里,#1绑定左值参考。 #2属于[over.ics.rank]

  

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

arr被隐式转换为int*类型的prvalue,然后绑定到b

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

  • 一个右值引用,通常绑定到右值。这显然是铿锵的解释。右值引用绑定到arr的prvalue转换中实现的临时值。
  • 具体而言,参数表达式是绑定到右值引用参数的右值。这显然是gcc的解释,因为arr不是右值(它是一个左值),所以这个决胜局被跳过,没有后续的破坏者适用。

我倾向于支持gcc在这里的实施。否则,短语“将rvalue引用绑定到rvalue”的意义是什么? Rvalue引用不能绑定到左值。这是多余的。也就是说,这种解释也措辞笨拙。

原样,我称之为措辞错误。