Barnett Barnett - 3 months ago 25
C++ Question

C++ Inheriting constructor from private template class

Why does class

D
compile, but class
C
does not?

class A
{
public:
A( int ) {}
};

template <class T>
class B : private T // Note: private base class
{
public:
using T::T;
};

class C : public B<A>
{
public:
C() : B<A>( 123 ) {} // Error: 'class A A::A' is inaccessible
}; // within this context

using BA = B<A>;

class D : public BA
{
public:
D() : BA( 123 ) {} // OK
};


I tested with GCC, Clang and Visual C++ and they are all the same.

Changing
class B : private T
to
public T
solves the problem.

But why? (Note that the
using T::T
is
public
.)

Answer

Class A contains the injected-class-name A within its scope (that is, A::A refers to class A unless it happens to refer to the constructor).

Class B inherits this, so the name A within the scope of B refers to the injected-class-name A in scope of A. However, since A is a private base class of B, all names in scope of A are private within B.

Class C again inherits this, but it cannot access this A, since it is private within B. Hence the error. Note that the error is actually with using the name A in the construct B<A>.

Class BA doesn't have this problem, since the definition B<A> is not in the scope of any class, so the name A refers to the global name A and not to any injected-class-name. And of course, the name BA is public.

You can easily solve this by qualifying the name A in C:

class C : public B<A>
{
public:
  C() : B<::A>( 123 ) {}
};

Note that constructor inheritance has no effect there. The problem is with access to the class name A (injected in A and inherited in B and C), not with access to the constructor.

Comments