Подтвердить что ты не робот

Почему компилятор выбирает конструктор базового класса внутри списка аргументов шаблона?

Последующий вопрос до этого.

В основном, в следующем коде, почему компилятор считает, что конструктор B внутри A<B> в C ссылается на конструктор (недоступный) базового класса B?

struct B{};

template <typename T>
struct A : private T{};

struct C : public A<B>{                                                                             
    C(A<B>);   // ERROR HERE
};

Пример Live на Ideone. Выход:

prog.cpp: 1: 9: ошибка: "структура B B:: B" недоступна
prog.cpp: 7: 7: ошибка: в этом контексте

Обратите внимание, что эта же ошибка появляется, если вы изменяете аргумент конструктора на A<B*>, A<B&> или даже A<const B>. Также обратите внимание, что три из MSVC10, GCC 4.7 и Clang 3.1 ToT будут выходить из строя, поэтому это должно быть что-то в спецификации С++. Что это такое?

4b9b3361

Ответ 1

Стандарт позволяет вводить имена классов менее доступными, чем исходные имена. Об этом даже упоминается в примечании в §11.1/5 вместе с примером:

[Примечание. В производном классе поиск имени базового класса будет найдите имя введенного класса вместо имени базового класса в область, в которой она была объявлена. Имя, указанное в виде инъекций, может быть менее доступным, чем имя базового класса в области, в которой было объявлено. -end note]

[Пример:

class A { };
class B : private A { };
class C : public B {
  A *p; // error: injected-class-name A is inaccessible
  ::A *q; // OK
};

-end пример]

Доступ к A unqualified использует введенное имя, которое недоступно, поскольку оно происходит из частного наследования. Доступ к A qualified использует объявленное имя, доступное в глобальной области.