Search code examples
c++c++11constructorlanguage-lawyerc++17

C++ Default constructor not inherited with "using" when move and copy constructors present


class A{

public:
    A(){};

};

class B : public A{

public:
    using A::A;

    B(const B&) =   default;
    B(      B&&) =  default;

};

B b;

The compiler (g++ (5.4.0-6ubuntu1) / c++11) says "no matching function for call to B::B()" and lists the copy and move constructors as candidates. If I comment those defaulted ones out then it compiles. What causes this? And what difference does it make that they are explicitly defaulted? If those 2 lines weren't there they would be defaulted anyway.


Solution

  • Before C++17, the default constructor of the base class won't be inherited via using:

    All candidate inherited constructors that aren't the default constructor or the copy/move constructor and whose signatures do not match user-defined constructors in the derived class, are implicitly declared in the derived class. (until C++17)

    After C++17 the code works fine.

    Before that, the default constructor won't be inherited from the base class, and won't be generated for class B because copy/move constructor are provided.

    If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.

    That's why if you comment copy/move constructor out it compiles. You can add the definition explicitly as a pre-C++17 workaround. e.g.

    class B : public A {
    public:
        B(const B&) =   default;
        B(      B&&) =  default;
    
        B() = default;
    };
    

    The code compiles with gcc8.