Inheriting a constructor from a private template class in C++
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
.)
Solution 1:
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.