43

Assuming the following layout:

class Base
{
protected:
    Base(P1 p1, P2 p2, P3 p3);

public:
    virtual void SomeMethod() = 0;
}

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

public:
    virtual void SomeMethod() override;
};

Should I be able to specify Derived's constructor as public here? VC++ gives the following error:

cannot access protected member declared in class 'Derived'
compiler has generated 'Derived::Derived' here [points to the using Base::Base line]
see declaration of 'Derived'

i.e. it's ignoring the access modifier above the inherited constructor.

Is this a limitation of the feature? It doesn't make any sense for the Base class to have a public constructor, as it can never be instantiated directly (due to the pure virtual method).

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230

1 Answers1

35

According to 12.9/4, "Inheriting constructors", when saying using X::X,

A constructor so declared has the same access as the corresponding constructor in X.

So the inherited constructor is also protected.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 8
    Wait what's so special about constructors? The same thing doesn't apply to regular functions... – user541686 Jan 09 '14 at 09:29
  • 3
    @Mehrdad [namespace.udecl]/18 has: "The alias created by the using-declaration has the usual accessibility for a member-declaration. [ Note: A using-declaration that names a constructor does not create aliases; see 12.9 for the pertinent accessibility rules. — end note ]" – TemplateRex Jan 09 '14 at 09:54
  • @TemplateRex: Great quote! I do wonder why the special case for constructors though, like we don't have enough inconsistencies already... – Matthieu M. Jan 09 '14 at 10:11
  • 3
    @MatthieuM. I have no idea, it has been in the draft papers since the very beginning, without explanation. And it's indeed kind of ironic that a proposal aimed at making constructors more regular w.r.t. ordinary functions, still leaves this small inconsistency. – TemplateRex Jan 09 '14 at 10:14
  • @MatthieuM.: It's a good question *why* constructors are different from member functions, but given that they are (in many senses), I'm sure there's a good reason for this rule. I'll have to think about it, though. Perhaps there's a clue in the original proposal? – Kerrek SB Jan 09 '14 at 10:41
  • 2
    @MatthieuM.: So, the only mention of this discussion is in [N1583](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1583.pdf), which is the cited source between revisions [N2203](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2203.html) and [N2254](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2254.html), where this was changed. But it's not an actual argument, just a note that this needed clarification. – Kerrek SB Jan 09 '14 at 11:44
  • @KerrekSB: interestingly, this means that `using Base::Base` is different than a forwarding constructor... – Matthieu M. Jan 09 '14 at 12:44
  • 2
    @MatthieuM.: Yes - the `using` declaration makes *all* eligible base constructors visible, not just one, too. – Kerrek SB Jan 09 '14 at 12:48
  • 1
    @KerrekSB: well, *this* is inline with overloaded methods in the base class; I was just referring to this strange accessibility issue since a forwarding constructor *redefines* the accessibility whilst a `using Base::Base` does not :/ – Matthieu M. Jan 09 '14 at 14:50
  • 1
    Is this still true in C++14? – Joseph Garvin Sep 18 '15 at 14:34
  • 1
    @JosephGarvin: I think so, the wording is still the same in the WD even. – Kerrek SB Sep 18 '15 at 14:37
  • 7
    Has anyone submitted a defect/RFC/whatever about this? It seems wrong. – underscore_d May 25 '17 at 18:06