3
votes

If I understand correctly:

class Base { /*...*/ };
class Derived: public Base { public: using Base::Base; }

will enforce inheritance of all Base constructors in Derived.

But what about public/protected/private constructors?

class Base {
    friend void g();
public:
    Base (A a);
protected:
    Base (B b);
private:
    Base (C c);
};

class Derived: public Base {
public:
    using Derived::Derived;
};

I can't find any specification on this, but I tried the following:

void f () {
    Derived{A{}}; // OK
    Derived{B{}}; // Inaccessible
    Derived{C{}}; // Inaccessible
}

void g () {
    Derived{A{}}; // OK
    Derived{B{}}; // OK
    Derived{C{}}; // OK
}

So it seems, that using Base::Base doesn't take the access modifiers into consideration when deciding which constructors to inherit (it inherits the private one) but it inherits them with those modifiers (private/protected ones remain inaccessible to others) and it allows private/protected access to friends of Base (friendship is not inherited, so g is not a friend of Derived, but it still can access private/protected constructor of Derived inherited from Base).

Is that correct and standard behaviour?

1

1 Answers

2
votes

The specification you are looking for is in [namespace.udecl] ΒΆ19, emphasis mine.

A using-declarator that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored.

Your testing is consistent with that paragraph. The accessibility checks fail or pass exactly as they would when constructing a Base in the scopes you check.