Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous overload for operator= using move assign and pass by value copy assign

If I define a copy assignment operator that invokes the copy constructor using pass by value for class thing:

thing& operator= (thing x) {

and a move assignment operator for the same class:

thing& operator= (thing&& x) {

Trying to invoke the move assignment results in an error from gcc:

error: ambiguous overload for ‘operator=’ (operand types are ‘thing’ and ‘std::remove_reference<thing&>::type {aka thing}’)

However, if the copy assign instead uses pass by reference:

thing& operator= (thing& x) {

Compilation is fine, and both operators can be invoked. Why is this?

Complete C++11 test code:

#include <iostream>
#include <utility>

using namespace std;

class thing {
    public:
        thing () { }
        thing (thing& x) {
            cout << "Copy constructor.\n";
        }
        thing (thing&& x) {
            cout << "Move constructor.\n";
        }
        thing& operator= (thing x) {
            cout << "Copy assign using pass by value.\n";
            return *this;
        }
        thing& operator= (thing&& x) {
            cout << "Move assign.\n";
            return *this;
        }
};


int main (void) {
    thing a, b;
// Invoke move assignment:
    a = move(b);
    return 0;
}                        
like image 778
CodeClown42 Avatar asked Jun 26 '14 16:06

CodeClown42


1 Answers

  • Calling move(b) returns an rvalue.

  • Both operator=(thing &&x) and operator=(thing x) can accept rvalues as input.

  • As such, the two overloads are ambiguous and the compiler rightfully complains because it can't choose between them.

like image 92
101010 Avatar answered Oct 22 '22 14:10

101010