分配给测试< /代码>,因为没有该调用的候选匹配,它将考虑最多转换1的操作。,c++,gcc,clang,overload-resolution,C++,Gcc,Clang,Overload Resolution" /> 分配给测试< /代码>,因为没有该调用的候选匹配,它将考虑最多转换1的操作。,c++,gcc,clang,overload-resolution,C++,Gcc,Clang,Overload Resolution" />

重载运算符在Clang上有歧义,但在GCC上没有,哪一个是正确的? #包括 模板 结构包装器{ 运算符T常量&(()常量&){ 我认为gcc和icc是正确的 #include <iostream> template <typename T> struct Wrapper { operator T const &() const & { std::cout << "Wrapper::operator T const &() const &\n"; return _obj; } operator T&() & { std::cout << "Wrapper::operator T&() &\n"; return _obj; } operator T&&() && { std::cout << "Wrapper::operator T&&() &&\n"; return std::move(_obj); } private: T _obj; }; struct Test { Test& operator=(Test const &test) { std::cout << "Test& Test::operator=(Test const &)\n"; return *this; } Test& operator=(Test &&test) { std::cout << "Test& Test::operator=(Test &&)\n"; return *this; } }; int main() { Test test; Wrapper<Test> wrapperTest; test = wrapperTest; // OK for all test = std::move(wrapperTest); // OK for GCC and ICC, not for Clang and VC++ return 0; } 将包装器&&代码>分配给测试< /代码>,因为没有该调用的候选匹配,它将考虑最多转换1的操作。

重载运算符在Clang上有歧义,但在GCC上没有,哪一个是正确的? #包括 模板 结构包装器{ 运算符T常量&(()常量&){ 我认为gcc和icc是正确的 #include <iostream> template <typename T> struct Wrapper { operator T const &() const & { std::cout << "Wrapper::operator T const &() const &\n"; return _obj; } operator T&() & { std::cout << "Wrapper::operator T&() &\n"; return _obj; } operator T&&() && { std::cout << "Wrapper::operator T&&() &&\n"; return std::move(_obj); } private: T _obj; }; struct Test { Test& operator=(Test const &test) { std::cout << "Test& Test::operator=(Test const &)\n"; return *this; } Test& operator=(Test &&test) { std::cout << "Test& Test::operator=(Test &&)\n"; return *this; } }; int main() { Test test; Wrapper<Test> wrapperTest; test = wrapperTest; // OK for all test = std::move(wrapperTest); // OK for GCC and ICC, not for Clang and VC++ return 0; } 将包装器&&代码>分配给测试< /代码>,因为没有该调用的候选匹配,它将考虑最多转换1的操作。,c++,gcc,clang,overload-resolution,C++,Gcc,Clang,Overload Resolution,发件人: 当用作函数参数且函数有两个重载可用时(一个使用右值引用参数,另一个使用左值引用常量参数),右值绑定到右值引用重载(因此,如果复制构造函数和移动构造函数都可用,则右值参数将调用移动构造函数,复制和移动赋值运算符也是如此) 以及: 非静态成员函数可以用左值ref限定符(函数名后面的标记和)或右值ref限定符(函数名后面的标记和)声明。在重载解析过程中,类X的非静态cv限定成员函数被视为一个函数,如果它没有ref限定符,或者如果它有lvalue ref限定符,则将lvalue referen

发件人:

当用作函数参数且函数有两个重载可用时(一个使用右值引用参数,另一个使用左值引用常量参数),右值绑定到右值引用重载(因此,如果复制构造函数和移动构造函数都可用,则右值参数将调用移动构造函数,复制和移动赋值运算符也是如此)

以及:

非静态成员函数可以用左值ref限定符(函数名后面的标记和)或右值ref限定符(函数名后面的标记和)声明。在重载解析过程中,类X的非静态cv限定成员函数被视为一个函数,如果它没有ref限定符,或者如果它有lvalue ref限定符,则将lvalue reference类型的隐式参数带到cv限定X。否则(如果它有rvalue ref限定符),它被视为一个函数,该函数将类型为rvalue的隐式参数引用到cv限定X

现在,我们有这些候选人:

  • Test&operator=(Test&Test)
    by
    operator T&&()&&
  • Test&operator=(Test const&Test)
    by
    operator T const&()const&

根据这些段落,编译器应该选择
Test&operator=(Test&Test)
by
operator T&&()和< <代码> > /p>你的例子是什么?代码> G++<代码>?你提供了<代码> VC++<代码>,但是你的问题的标题是“代码> G++<代码>。是什么?VisualStudioC++是一个不同于GNU G++的编译器。我很困惑。它们都提到同样的问题:<代码>运算符=()。
模棱两可。这有什么不同呢?@ThomasMatthews我说这段代码在GCC上编译得很好,但在Clang和VC++上编译不好,我把错误消息放在Clang和VC++上。@Deduplicator但显式的右值转换将不会被调用,不?等等,
&
&
函数说明符做了什么?我第一次看到也许这个答案也应该引用页面?为什么编译器应该选择
&&
重载?这两个隐式转换序列是无法区分的用户定义转换序列,因为它们不包含相同的用户定义转换函数().据我所知,这个调用确实不明确。@bogdan,但因为std::move(wrapperTest)是一个右值,由于转换运算符上的ref限定符,它应该选择右值版本,否?@Johnmph
&&
const&
都可以绑定到一个右值,因此转换函数的
const&
重载对于ref限定符来说是一个可行的候选者两个赋值运算符函数各自参数的两个引用绑定取决于引用绑定的规则();由于长段落中项目符号的顺序,对于绑定
const Test&
而言,首选
const&
转换函数重载,对于
Test&
而言,首选
&
一个。正如@bogdan所解释的,重载是不明确的。在
运算符T&&()&&&
解决了这个问题。顺便说一句,我对clang发现这个问题并不感到惊讶,但我对VC++发现这个问题感到惊讶。。。
test = std::move(wrapperTest);