When the using-declaration is used to inherit constructors, it requires a direct base class [namespace.udecl]/3
If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined; otherwise it introduces the set of declarations found by member name lookup.
I.e. in your case, the using-declaration in OperationFailedBecauseFileDoesNotExistError
doesn't inherit, but re-declares (as an alias), or unhides, the name of the ctor of ExceptionBase
.
You'll have to write a non-inheriting ctor for OperationFailedBecauseFileDoesNotExistError
.
By the way, this is fine for non-virtual base classes: The using-declaration for inheriting ctors is rewritten as:
//using ExceptionBase::ExceptionBase;
OperationFailure(char const * msg)
: ExceptionBase( static_cast<const char*&&>(msg) )
{}
As you may only initialize a direct base class (or virtual base class) in the mem-initializer-list, it makes sense for non-virtual base classes to restrict the using-declaration to inherit ctors only from direct base classes.
The authors of the inheriting ctors proposal have been aware that this breaks support for virtual base class ctors, see N2540:
Typically, inheriting constructor definitions for classes with virtual bases will be ill-formed, unless the virtual base supports default initialization, or the virtual base is a direct base, and named as the base forwarded-to. Likewise, all data members and other direct bases must support default initialization, or any attempt to use a inheriting constructor will be ill-formed. Note: ill-formed when used, not declared.