Возможно, мое понимание [class.access]/7 неверно, но
Из [class.access]/7 мы имеем следующее предложение:
Аналогично, использование A::B
в качестве базового спецификатора хорошо сформировано потому что D
получается из A
, поэтому проверка базовых спецификаторов должна отложить до тех пор, пока не будет просмотрен весь список-спецификатор базы.
class A {
protected:
struct B { };
};
struct D: A::B, A { };
Смотрите живой пример с clang. На самом деле, clang также жалуется на этот фрагмент, где отсрочка не требуется.
class A {
protected:
struct B { };
};
struct D: A, A::B { };
Почему этот код не компилируется?
PS: gcc и VS21013 также не компилируют коды.
Ответы
Ответ 1
Это просто ошибка компилятора. Этот пример соответствует нормативному тексту стандарта. Тот факт, что несколько компиляторов имеют одну и ту же ошибку, означает, что это часть стандарта, сложно получить.
Есть открытые ошибки об этом для GCC
и для clang. Обратите внимание, что несколько связанных случаев - это на самом деле тонкие различия между С++ 03 и С++ 11, но, насколько я могу судить, не этот.
[class.access]/1.2 просто указывает
protected
; то есть его имя может использоваться только членами и друзьями класса, в котором он объявлен, классами, полученными из этого класса, и их друзьями (см. п. 11.4).
и 11.4 на этом не расширяется. Вы используете имя B
в классе D
, полученном из этого класса A
. Это прекрасно.
Ответ 2
Я считаю, что это ошибка с clang. Ideone не принимает код: http://ideone.com/uiFl9L:
class A {
protected:
struct B { };
};
struct D: A::B, A { };
Я проверил gcc-5.1.0, gcc-4.9 и clang-3.7 (rc2). В стандарте явно указано это как правильно сформированное (см. Вопрос), поэтому компиляторы ошибаются.
В примере очищается [class.access]/6:
Все элементы управления доступом в разделе 11 влияют на возможность доступа к имени члена класса из объявления конкретный объект, включая части объявления, предшествующие имени объявляемого объекта...
Это означает, что согласно [class.access]/2 класс имеет доступ ко всем базовым классам, даже до их объявления.