1

I'm in a situation where I need to implement Move Constructor and Move-Assignment Operator for a class which holds a reference to an object with a deleted Copy Ctor and Copy-Assignment Operator, basically looks like this:

class MoveOnlyThing
{
public:
    MoveOnlyThing() = default;
    MoveOnlyThing(const MoveOnlyThing&) = delete;
    MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
};

class Holder
{
public:
    Holder(MoveOnlyThing& t)
    : mThing(t)
    {
    }
    
    Holder(Holder&& other)
    : mThing(other.mThing)
    {
    }
    
    Holder& operator=(Holder&& other)
    {
        mThing = other.mThing;
        return *this;
    }
    
    MoveOnlyThing& mThing;
};

Now, the problem is, the assignment of mThing = other.mThing; is emitting an error:

main.cpp:40:16: error: overload resolution selected deleted operator '='
        mThing = other.mThing;
        ~~~~~~ ^ ~~~~~~~~~~~~
main.cpp:20:12: note: candidate function has been explicitly deleted
    MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
           ^

Two questions are raised;

  1. How do we deal with this? Implement the Move Constructor, and then use this to implement the Move-Assignment Operator?
  2. I didn't realize that the compiler would generate a copy in this case when re-assigning an existing reference. Who can explain that?
yano
  • 4,095
  • 3
  • 35
  • 68
  • 4
    You can't assign a reference. Only initialize. – user4581301 Sep 21 '21 at 20:30
  • 4
    You are misunderstanding the meaning of `mThing = other.mThing;`. It does not mean "Assign a new value to the reference `mThing`", it means "Assign a new value to (the object pointed to by `mThing`)". References perform indirection implicitly, **any time you use the name of a reference you actually get the object it is pointing to**. – Ben Voigt Sep 21 '21 at 20:33
  • 1
    @BenVoigt yes that is correct, so actually the reason its trying to invoke the copy constructor is to assign to the *original object* thanks for pointing that out – yano Sep 21 '21 at 20:44
  • You need `std::move()` in order to invoke `MoveOnlyThing`'s move assignment operator: `mThing = std::move(other.mThing);` – Remy Lebeau Sep 21 '21 at 20:48

0 Answers0