gpt4 book ai didi

c++ - Clang 上的重载运算符歧义,但 GCC 上没有,哪个是正确的?

转载 作者:太空狗 更新时间:2023-10-29 20:54:08 27 4
gpt4 key购买 nike

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

VC++:

(34): error C2593: 'operator =' is ambiguous

(26): note: could be 'Test &Test::operator =(Test &&)'

(25): note: or 'Test &Test::operator =(const Test &)'

(69): note: while trying to match the argument list '(Test, Wrapper)'

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

clang :

:34:7: error: use of overloaded operator '=' is ambiguous (with operand types 'Test' and 'typename std::remove_reference &>::type' (aka 'Wrapper'))

test = std::move(wrapperTest); // OK for GCC and ICC, not for Clang and Microsoft Visual C++

~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~

:25:8: note: candidate function

Test& operator=(Test const &test) { std::cout << "Test& Test::operator=(Test const &)\n"; return *this; }

^

:26:8: note: candidate function

Test& operator=(Test &&test) { std::cout << "Test& Test::operator=(Test &&)\n"; return *this; }

^

1 error generated.

最佳答案

我认为 gcc 和 icc 是正确的。

test = std::move(wrapperTest);

分配一个 Wrapper<Test>&&Test , 由于此调用没有候选匹配项,因此它将考虑最多需要 1 次转换的操作。

来自 Value categories :

When used as a function argument and when two overloads of the function are available, one taking rvalue reference parameter and the other taking lvalue reference to const parameter, an rvalue binds to the rvalue reference overload (thus, if both copy and move constructors are available, an rvalue argument invokes the move constructor, and likewise with copy and move assignment operators).

Non-static member functions :

A non-static member function can be declared with either an lvalue ref-qualifier (the token & after the function name) or rvalue ref-qualifier (the token && after the function name). During overload resolution, non-static cv-qualified member function of class X is treated as a function that takes an implicit parameter of type lvalue reference to cv-qualified X if it has no ref-qualifiers or if it has the lvalue ref-qualifier. Otherwise (if it has rvalue ref-qualifier), it is treated as a function taking an implicit parameter of type rvalue reference to cv-qualified X.

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

  • Test& operator=(Test &&test)通过 operator T&&() &&
  • Test& operator=(Test const &test)通过 operator T const &() const &

基于这些段落,编译器应该选择 Test& operator=(Test &&test)通过 operator T&&() &&

关于c++ - Clang 上的重载运算符歧义,但 GCC 上没有,哪个是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40221969/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com