2

In C++11, we get an ambiguity error from the compiler (g++) if we make the following definitions:

C& operator=(C rhs)
{
    swap(*this, rhs);
    return *this;
}

C& operator=(C&& rhs)
{
    swap(*this, rhs);
    return *this;
}

It is not entirely clear to me why there is an ambiguity. In my understanding, the compiler can tell apart what is an rvalue object and what is not at compile time. So it could make a decision to call the latter for rvalue objects and the former for lvalue objects. I am probably missing something basic but an explanation would be great.

user3560270
  • 413
  • 2
  • 7
  • 1
    whats the benefit of the `&&` variant here? its not typically part of the [copy-and-swap idiom](https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom), is it? – kmdreko Apr 13 '18 at 03:59
  • The && variant would allow c1 = c2 + c3 to be performed without an extra copy of c2 + c3 to rhs. – user3560270 Apr 13 '18 at 04:30
  • You're right that the first would have an extra move, but most [C++11 implementations of the copy-and-swap idiom](https://stackoverflow.com/questions/37915088/a-better-way-to-implement-copy-and-swap-idiom-in-c11) that I've seen indicate you should use the `C` option, or if you want the optimization, `const C&` and `C&&` as normal. The answer [here](https://stackoverflow.com/questions/17961719/overload-resolution-between-object-rvalue-reference-const-reference) indicates that `C` and `C&&` are ambiguous for overloading – kmdreko Apr 13 '18 at 05:17

1 Answers1

1

The argument must be passed through const reference to resolve the ambiguity.

C& operator=(const C& rhs)
{
    swap(*this, C(tmp));
    return *this;
}

Since your class C has a moving constructor C::C(C&&) (I think it is so, you did not provide Minimal, Complete, and Verifiable example) then it causes the ambiguity between operator=(C rhs) and operator=(C&& rhs).

273K
  • 29,503
  • 10
  • 41
  • 64