Наследование конструктора из частного шаблона в С++

Почему класс D компилируется, но класс C не работает?

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
};

Я тестировал GCC, Clang и Visual С++, и они все одинаковы. Изменение class B : private T до public T решает проблему. Но почему? (Обратите внимание, что using T::T - public.)

Ответ 1

Класс A содержит введенное имя класса A в своей области (то есть A::A относится к классу A, если только это не относится к конструктору).

Класс B наследует это, поэтому имя A в пределах области B относится к введенному классу-названию A в области A. Однако, поскольку A является частным базовым классом B, все имена в области A являются частными внутри B.

Класс C снова наследует это, но он не может получить доступ к этому A, поскольку он является закрытым в пределах B. Отсюда и ошибка. Обратите внимание, что ошибка на самом деле связана с использованием имени A в конструкции B<A>.

Класс BA не имеет этой проблемы, так как определение B<A> не входит в сферу применения любого класса, поэтому имя A относится к глобальному имени A, а не к любому введенному классу -имя. И, конечно, имя BA является общедоступным.

Вы можете легко решить это, присвоив имя A в C:

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

Обратите внимание, что наследование конструктора не действует. Проблема заключается в доступе к имени класса A (введенному в A и унаследованному в B и C), а не к доступу к конструктору.