Search code examples
c++inheritancec++11moveusing-declaration

Inheriting parent assignment operator when child's is implicitly deleted


In GCC 4.6, it is possible to inherit a parent's assignment operators even when the child's assignment operators are implicitly deleted due to a move constructor. In later versions of GCC (as well as Clang), this is no longer possible. What is the proper way to have the child class use the parent's assignment operators?

struct A
{
  A & operator=(A const & other) = default;
};

struct B : public A
{
  B() {}
  B(B && other) {}

  using A::operator=;
};

int main()
{
  B b1, b2;
  b1 = b2; // error: use of deleted function because B's operator= is implicitly deleted due to move constructor
  return 0;
}

Solution

  • A function that is deleted is still declared, only the definition is deleted. Expanding that in your class definition:

    struct B : A {
       using A::operator=;               // A& operator=(const A&)
       B& operator=(const B&) = delete;
    };
    

    At this point, you can note that there are two declarations for operator= in the derived type, the first one (brought into scope by means of a using-declaration) takes a const A& argument, while the second one takes a const B& and is deleted.

    When you later try the assignment:

    B b1, b2;
    b1 = b2;
    

    Both declarations are seen by the compiler and the second one is a better match. Because it is marked as deleted you get the error. If you had, on the other hand assigned a A object it would have worked as expected:

    B b1, b2;
    b1 = static_cast<A&>(b2); // works, BUT...
    

    The problem with this approach is that it is only copying the base subobjects which is probably not what you want. If you just want the same behavior you would have had if the assignment had been generated by the compiler you need to ask for it:

    struct B : A {
       // ...
       B& operator=(const B&) = default;
    };