也许我对 [class.access]/7 的理解不正确,但是

Maybe my understanding of [class.access]/7 isn't correct, but

从[class.access]/7我们有下面的句子:

Similarly, the use of A::B as a base-specifier is well-formed because D is derived from A, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen.

class A {
protected:
    struct B { };
};
struct D: A::B, A { };

请参阅 live example 和 clang。事实上,clang 也抱怨这个片段,不需要延迟。

class A {
protected:
    struct B { };
};
struct D: A, A::B { };

为什么这段代码无法编译?

PS: gcc 和 VS21013 也不编译代码。

我认为这是 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:

All access controls in Clause 11 affect the ability to access a class member name from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared ...

这意味着,根据 [class.access]/2,class 可以访问所有 base-classes,甚至在它们被声明之前。

这只是一个编译器错误。该标准的规范性文本支持示例。多个编译器具有相同错误的事实意味着这是标准的一部分很难正确处理。

有关于此的未解决的错误for GCCfor clang。请注意,一些相关案例实际上是 C++03 和 C++11 之间的细微差别,但据我所知,不是这个。

[class.access]/1.2 仅声明

protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see 11.4).

而11.4并没有对此展开。您在从 class A 派生的 class D 中使用名称 B。没关系。