【发布时间】:2022-01-25 23:20:20
【问题描述】:
#include <type_traits>
#include <iostream>
template<typename T>
struct Wrapper {
T value;
operator T&() & { std::cout << "call const ref" << std::endl; return this->value; }
operator const T&() const& { std::cout << "call const ref" << std::endl; return this->value; }
operator T&&() && { std::cout << "call move" << std::endl; return std::move(this->value); }
operator const T&() const&& = delete;
operator T&&() & = delete;
operator T&&() const& = delete;
};
class A {
public:
A& operator=(const A&) { std::cout << "use copy" << std::endl; return *this; }
A& operator=(A&&) { std::cout << "use move" << std::endl; return *this; }
};
int main() {
Wrapper<A> b;
A bb;
bb = std::move(b);
}
我用gcc10.2编译了这段代码,得到如下错误
test.cc: In function ‘int main()’:
test.cc:24:21: error: ambiguous overload for ‘operator=’ (operand types are ‘A’ and ‘std::remove_reference<Wrapper<A>&>::type’ {aka ‘Wrapper<A>’})
24 | bb = std::move(b);
| ^
test.cc:17:12: note: candidate: ‘A& A::operator=(const A&)’
17 | A& operator=(const A&) { std::cout << "use copy" << std::endl; return *this; }
| ^~~~~~~~
test.cc:18:12: note: candidate: ‘A& A::operator=(A&&)’
18 | A& operator=(A&&) { std::cout << "use move" << std::endl; return *this; }
| ^~~~~~~~
但我在 cppinsights.io 中用 clang 尝试了相同的代码,并且编译成功。 link
那么,是什么导致了 gcc 和 clang 之间的差异?
以及如何更改Wrapper 来修复它?
【问题讨论】:
-
您想将 Wrapper 对象移动到 A 对象。你确定吗?
-
cppinsights 使用 Clang,而 clang 可以使用 godbolt.org/z/45EbfGP3d
-
GCC 10.3 或 GCC 11.2 也有问题吗?
标签: c++ templates language-lawyer ambiguous