Возможно, мое понимание [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 класс имеет доступ ко всем базовым классам, даже до их объявления.