我在下面关于 C++ 标准中的 §9.3.1/3 的观察是否正确?
Am I correct in my observation below about §9.3.1/3 in the C++ Standard?
§9.3.1/3(重点是我的):
When an id-expression (5.1) that is not part of a class member access
syntax (5.2.5) and not used to form a pointer to member (5.3.1) is
used in a member of class X in a context where this can be used
(5.1.1), if name lookup (3.4) resolves the name in the id-expression
to a non-static non-type member of some class C, and if either the
id-expression is potentially evaluated or C is X or a base class of X,
the id-expression is transformed into a class member access expression
(5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of
the . operator. [ Note: If C is not X or a base class of X, the class
member access expression is ill-formed. — end note ] Similarly during
name lookup, when an unqualified-id (5.1) used in the definition of a
member function for class X resolves to a static member, an enumerator
or a nested type of class X or of a base class of X, the
unqualified-id is transformed into a qualified-id (5.1) in which the
nested-name-specifier names the class of the member function.
上面的注释不应该更具体吗?我的意思是这样的:`如果可能评估 id 表达式并且如果 C 不是 X 或 X 的基数 class,则 class 成员访问表达式格式错误。"
请注意,如果 id-expression 是未计算的操作数,即使 C 不是 X,也不是 X 的基数 class,代码仍然有效,尽管在这种情况下,段落中提到的转换将没有发生。
注释有点含糊,但我认为它的目的是对前一句的最后部分进行注释,好像写成这样:
and if either the id-expression is potentially evaluated or C is X or a base class of X, then:
- the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator. [ Note: If C is not X or a base class of X, the class member access expression is ill-formed. — end note ]
当这样阅读时,注释是完全正确的。
无论如何,注释不是规范的,所以即使措辞有疑问,也没关系,因为它对任何 C++ 程序或实现没有任何影响:没有程序变得有效或由于本说明的措辞而无效,并且由于本说明,没有实现符合或不符合。在最坏的情况下,就像这里发生的那样,理解标准变得更加困难,导致误解。
正如 Columbo 在评论中提到的那样,实施者的这种误解可能会导致不符合要求的实施,但这不是这里发生的事情。
该注释基本上意味着,如果您使用 C::member
作为变量(而不仅仅是确定其类型、对齐方式或大小),则该程序显然是非良构的。
一个例子是
class C
{
int member;
};
class X
{
void memfun()
{
// Note that 'this' can be used here
C::member = 3; // member is potentially evaluated ([basic.def.odr]/2).
// Thus the expression is transformed into
// (*this).member
// which is clearly ill-formed.
}
};
程序格式错误,因为 member
没有任何 "to do" 和 X
(它不是 X
的成员或任何基 class 其中)并可能对其进行评估。
引用是适当的(虽然多余)。
但是,为什么 sizeof(C::member)
不是病式的呢?因为 C::member
可能未被评估。
An expression is potentially evaluated unless it is an unevaluated
operand (Clause 5) or a subexpression thereof.
和[expr.sizeof]:
The operand is either an expression, which is an unevaluated
operand (Clause 5), or a parenthesized type-id.
因此没有转换 id 表达式。
所以这张便条来自 defect report 515 2005 年,当时的措辞不同:
When an id-expression (5.1.1 [expr.prim.general]) that is not part of
a class member access syntax (5.2.5 [expr.ref]) and not used to form a
pointer to member (5.3.1 [expr.unary.op]) is used in the body of a
non-static member function of class X or used in the mem-initializer
for a constructor of class X, if name lookup (3.4.1
[basic.lookup.unqual]) resolves the name in the id-expression to a
non-static non-type member of some class C, the id-expression is
transformed into a class member access expression (5.2.5 [expr.ref])
using (*this) (9.3.2 [class.this]) as the postfix-expression to the
left of the . operator. [Note: If C is not X or a base class of X, the
class member access expression is ill-formed. —end note]
并且有所演变,注意当前的写法前注意:
or C is X or a base class of X, the id-expression
在这个早期的措辞中没有出现,所以有澄清说明更有意义,在这一点上,说明似乎是多余的。
§9.3.1/3(重点是我的):
When an id-expression (5.1) that is not part of a class member access syntax (5.2.5) and not used to form a pointer to member (5.3.1) is used in a member of class X in a context where this can be used (5.1.1), if name lookup (3.4) resolves the name in the id-expression to a non-static non-type member of some class C, and if either the id-expression is potentially evaluated or C is X or a base class of X, the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator. [ Note: If C is not X or a base class of X, the class member access expression is ill-formed. — end note ] Similarly during name lookup, when an unqualified-id (5.1) used in the definition of a member function for class X resolves to a static member, an enumerator or a nested type of class X or of a base class of X, the unqualified-id is transformed into a qualified-id (5.1) in which the nested-name-specifier names the class of the member function.
上面的注释不应该更具体吗?我的意思是这样的:`如果可能评估 id 表达式并且如果 C 不是 X 或 X 的基数 class,则 class 成员访问表达式格式错误。"
请注意,如果 id-expression 是未计算的操作数,即使 C 不是 X,也不是 X 的基数 class,代码仍然有效,尽管在这种情况下,段落中提到的转换将没有发生。
注释有点含糊,但我认为它的目的是对前一句的最后部分进行注释,好像写成这样:
and if either the id-expression is potentially evaluated or C is X or a base class of X, then:
- the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator. [ Note: If C is not X or a base class of X, the class member access expression is ill-formed. — end note ]
当这样阅读时,注释是完全正确的。
无论如何,注释不是规范的,所以即使措辞有疑问,也没关系,因为它对任何 C++ 程序或实现没有任何影响:没有程序变得有效或由于本说明的措辞而无效,并且由于本说明,没有实现符合或不符合。在最坏的情况下,就像这里发生的那样,理解标准变得更加困难,导致误解。
正如 Columbo 在评论中提到的那样,实施者的这种误解可能会导致不符合要求的实施,但这不是这里发生的事情。
该注释基本上意味着,如果您使用 C::member
作为变量(而不仅仅是确定其类型、对齐方式或大小),则该程序显然是非良构的。
一个例子是
class C
{
int member;
};
class X
{
void memfun()
{
// Note that 'this' can be used here
C::member = 3; // member is potentially evaluated ([basic.def.odr]/2).
// Thus the expression is transformed into
// (*this).member
// which is clearly ill-formed.
}
};
程序格式错误,因为 member
没有任何 "to do" 和 X
(它不是 X
的成员或任何基 class 其中)并可能对其进行评估。
引用是适当的(虽然多余)。
但是,为什么 sizeof(C::member)
不是病式的呢?因为 C::member
可能未被评估。
An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof.
和[expr.sizeof]:
The operand is either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id.
因此没有转换 id 表达式。
所以这张便条来自 defect report 515 2005 年,当时的措辞不同:
When an id-expression (5.1.1 [expr.prim.general]) that is not part of a class member access syntax (5.2.5 [expr.ref]) and not used to form a pointer to member (5.3.1 [expr.unary.op]) is used in the body of a non-static member function of class X or used in the mem-initializer for a constructor of class X, if name lookup (3.4.1 [basic.lookup.unqual]) resolves the name in the id-expression to a non-static non-type member of some class C, the id-expression is transformed into a class member access expression (5.2.5 [expr.ref]) using (*this) (9.3.2 [class.this]) as the postfix-expression to the left of the . operator. [Note: If C is not X or a base class of X, the class member access expression is ill-formed. —end note]
并且有所演变,注意当前的写法前注意:
or C is X or a base class of X, the id-expression
在这个早期的措辞中没有出现,所以有澄清说明更有意义,在这一点上,说明似乎是多余的。