#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;
}
答案 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转换中实现的临时值。 arr
不是右值(它是一个左值),所以这个决胜局被跳过,没有后续的破坏者适用。我倾向于支持gcc在这里的实施。否则,短语“将rvalue引用绑定到rvalue”的意义是什么? Rvalue引用不能绑定到左值。这是多余的。也就是说,这种解释也措辞笨拙。
原样,我称之为措辞错误。