overload resolution between lvalue reference and rvalue reference

旧巷老猫 提交于 2021-02-18 09:55:50

问题


#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:

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

...

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?

Updated:

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

回答1:


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 and S2 are reference bindings 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

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

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

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

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 is implicitly converted to a prvalue of type int*, which is then bound to b.


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

  • 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.

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.



来源:https://stackoverflow.com/questions/46116173/overload-resolution-between-lvalue-reference-and-rvalue-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!