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

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.


If you declare any constructors, the default constructor is not implicitly generated, you can generate it by adding a = default for it as well:

class B : public A {

public:

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

This has changed with C++17 (as pointed out by other answer).


The default constructor cannot be inherited, the standard explicitly says so. Quoting C++11 12.9 [class.inhctor]/3 (emphasis mine) (*):

For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the class where the using-declaration appears. ...

This means that for the default constructor, normal rules apply as if the using A::A; declaration wasn't there. So the presence of any other constructor declaration (such as the copy & move constructor) causes the default constructor not to be implicitly declared. Note that you can easily add it back by explicitly defaulting it:

class B : public A{

public:
    using A::A;

    B() = default;

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

};

(*) The same wording is present in C++14 (n4140), at the same location. I can't seem to find equivalent wording in C++1z (looking through n4582)