左值参考和右值参考之间的重载分辨率 [英] overload resolution between lvalue reference and rvalue reference

查看:63
本文介绍了左值参考和右值参考之间的重载分辨率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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;
}

两个函数都是完全匹配的.以下是该标准的引文:

Both functions are exact matches. Below is a quote from the standard:

标准转换序列S1比标准转换序列S2 if

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

...

S1和S2是参考绑定(8.5.3),均未引用声明的非静态成员函数的隐式对象参数没有ref限定词的情况下,S1将右值引用绑定到右值S2绑定一个左值引用.

S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.

不是暗示第二个更好吗?

Doesn't it imply that the second is better?

已更新:

那里.下面的代码是它的简化版本.

There is a related question. And the following code is a simplified version of it.

#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;
}

推荐答案

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

I think it depends on what a particular phrase means.

这两个转换是等效的,因为我们排除了左值转换(基本上,数组实际上是一个指针,因此它不算作转换),因此我们进入您在

Both conversions are equivalent because we exclude lvalue transformations (basically, an array effectively is a pointer so it doesn't count as a conversion), so we get into the next tiebreaker that you pointed out in [over.ics.rank]:

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

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

Does this case apply? We do have two reference bindings:

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

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

Here, #1 binds an lvalue reference. #2 falls into [dcl.init.ref]:

否则,初始化程序表达式将隐式转换为类型为"cv1 T1"的prvalue.应用临时物化转换,并将引用绑定到结果.

Otherwise, the initializer expression is implicitly converted to a prvalue of type "cv1 T1". The temporary materialization conversion is applied and the reference is bound to the result.

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

arr is implicitly converted to a prvalue of type int*, which is then bound to b.

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

So now the question is - what does the restriction in [over.ics.rank] mean? It could mean:

  • 通常绑定到右值的右值引用.这显然是clang的解释.右值引用绑定到 arr 的prvalue转换中实现的临时实例.
  • 具体地说,参数表达式是绑定到右值引用参数的右值.这显然是gcc的解释,并且由于 arr 不是右值(它是左值),因此该决胜局将被跳过,并且以后的决胜局均不适用.
  • an rvalue reference that is, in general, bound to an rvalue. This is apparently clang's interpretation. The rvalue reference is bound to the temporary materialized from the prvalue conversion of arr.
  • specifically, the argument expression is an rvalue that is bound to the rvalue reference parameter. This is apprently gcc's interpretation, and since arr is not an rvalue (it is an lvalue), this tiebreaker is skipped and no subsequent tiebreakers apply.

我倾向于在这里支持gcc的实现.否则,短语将右值引用绑定到右值"的意思是什么?右值引用不能绑定到左值.这是多余的.也就是说,这种解释也措辞尴尬.

I am inclined to favor gcc's implementation here. Otherwise, what would the point of the phrase "binds an rvalue reference to an rvalue" be? Rvalue references cannot bind to lvalues. It's redundant. That said, it's awkwardly worded for that interpretation too.

按原样,我将其称为文字错误.

As is, I'll call it a wording bug.

这篇关于左值参考和右值参考之间的重载分辨率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆