我哪里错了?查找名称 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 接受此代码,我认为这是一个错误。
我对 §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 接受此代码,我认为这是一个错误。