C++11 Inheriting Constructors and Access Modifiers

C++11 inheriting constructors and access modifiers

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.

C++11 inheriting constructors and access modifiers

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.

c++11 inheriting template constructors

This syntax

using sysTrajectory::sysTrajectory; 

Names all constructors of sysTrajectory. This syntax

using sysTrajectory::sysTrajectory<Real>;

Names only a constructors that accept a template argument <Real> (yes, you can do that, you can pass explicit template arguments to constructors in declarative contexts). Your base class does not appear to have any constructor templates, so your compiler's parser does not take sysTrajectory as a template-name and hence does not accept the < as an opening template argument list. Hence the syntax error.

For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.

Even if you had a constructor template, a rule for using declarations forbids that too. It says

A using-declaration shall not name a template-id.

Inheriting public/protected/private constructors

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.

using statement and protected constructor

This is intentional. Note that A::A inherits every constructor, not just the one you are expecting. Applying the using's access modifier to every inherited constructor would likely be too far reaching. Instead, it simply makes them available for overload resolution.

From cppreference :

If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.

If overload resolution selects an inherited constructor, it is accessible if it would be accessible when used to construct an object of the corresponding base class: the accessibility of the using-declaration that introduced it is ignored.

If you want to call A::A(int) when constructing a B, you can implement B::B(int) yourself such that it calls it.

Use of 'using' keyword to make inherited constructor public

The Standard explicitly states that inherited constructors retain their access levels:

12.9 Inheriting constructors [class.inhctor]

1 A using-declaration (7.3.3) that names a constructor implicitly
declares a set of inheriting constructors. The candidate set of
inherited constructors from the class X named in the using-declaration
consists of actual constructors and notional constructors that result
from the transformation of defaulted parameters as follows:

[list of cases omitted]

4 A constructor so declared has the same access as the corresponding
constructor in X
. It is deleted if the corresponding constructor in X
is deleted (8.4).

You can call it directly of course:

TestableFoo(int i) : Foo(i) { }

Overloading inherited constructors

In this case all you need to do is provide c with an in class initializer

class Derived : public Base {
using Base::Base;
bool c = true;
};

allows you to use Base's constructors and will initialize c to true in all cases.



Related Topics



Leave a reply



Submit