我哪里错了?查找名称 Node 会找到结构 Node 的 injected-class-name

Where am I wrong here? The lookup for the name Node finds the injected-class-name for the struct Node

我对 §3.4.4/3 (C++14) 示例中的第一条评论有疑问:

struct Node {
    struct Node* Next; // OK: Refers to Node at global scope
    struct Data* Data; // OK: Declares type Data
                       // at global scope and member Data
};

从 §3.3.2/7(见下文)可以得出结论,该评论是正确的,因为全局名称空间是包含声明 struct Node* Next; 的最小名称空间。

§3.3.2/7(我的重点)

The point of declaration of a class first declared in an elaborated-type-specifier is as follows:

  • for a declaration of the form

    class-key attribute-specifier-seqopt identifier ;

    the identifier is declared to be a class-name in the scope that contains the declaration, otherwise

  • for an elaborated-type-specifier of the form

    class-key identifier

    if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration. [ Note: These rules also apply within templates. —end note ] [ Note: Other forms of elaborated-type-specifier do not declare a new name, and therefore must refer to an existing type-name. See 3.4.4 and 7.1.6.3. —end note ]

但是从 §3.4.4/2(见下文)我得到的印象是查找名称 Node 找到注入的-class-名称 Node,所以它不能在全局范围内引用 Node

§3.4.4/2(我的重点)

If the elaborated-type-specifier has no nested-name-specifier, and unless the elaborated-type-specifier appears in a declaration with the following form:

class-key attribute-specifier-seqopt identifier ;

the identifier is looked up according to 3.4.1 but ignoring any non-type names that have been declared. If the elaborated-type-specifier is introduced by the enum keyword and this lookup does not find a previously declared type-name, the elaborated-type-specifier is ill-formed. If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name, or if the elaborated-type-specifier appears in a declaration with the form:

class-key attribute-specifier-seqopt identifier ;

the elaborated-type-specifier is a declaration that introduces the class-name as described in 3.3.2.

3.3.2 中的段落是关于声明 classes,而不是对象。

您的声明 struct Node* Next 不可能匹配“class-key identifier”;后者只匹配前者中一半的标记。

[basic.scope.pdecl]/7 的第一句清楚地表明该段涉及 a class 首先在 elaborated-type-specifier 中声明;因此它不适用于 struct Node* Next; 中的 struct Node,因为 Node 不是首先在 elaborated-type-specifier.[=16 中声明的=]

相反,Node 的非限定名称查找确实找到了 injected-class-name(参见 [basic.lookup.unqual]/p1和 7.1) 而不是 ::Node。不过,您需要为此编写一些相当人为的代码。例如:

struct A {};
struct B : private A {};
struct C : public B {
    struct A m_a; // error: A is the inaccessible injected-class-name, not ::A
    struct ::A m_a2; // OK
};

请注意,GCC 接受此代码,我认为这是一个错误。