c++scopenamespaceslanguage-lawyeridentifier

Where does the C++ standard allow an identifier with name space of a structure in a primary expression?


Where the C++ standard allows an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression?

Consider the following code (which is a valid C++, but an invalid C):

struct s
{
    int x;
    int y[sizeof x];
};

Here the sizeof is applied to structure member x while declaring the structure itself. This is allowed in C++ (and not in C) because:

  1. In C++ the x has class (and a struct is a class) scope. Therefore, as I understand, sizeof will search x in the class scope first.
  2. C++ seems to allow an identifier with name space of a structure (a "non-ordinary" identifier in C) in a primary expression (which is an operand of the sizeof).

To compare with C: C23 (n3299.pdf, 6.5.2p2) has the following constraint (emphasis added):

The identifier in an identifier primary expression shall have a visible declaration as an ordinary identifier that declares an object or a function.

This constraint invalidates the code above (being compiled as C code), because x is (at least) a non-ordinary identifier.


How does C++ treat / classify identifier x (e.g. as an identifier with name space struct s)?

Where does the C++ standard allow an identifier with name space of a structure in a primary expression?


Solution

  • [expr.prim.id.general]/4:

    An id-expression that denotes a non-static data member or implicit object member function of a class can only be used:

    • as part of a class member access (after any implicit transformation (see above)) in which the object expression refers to the member's class or a class derived from that class, or
    • to form a pointer to member ([expr.unary.op]), or
    • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.

    The operand of sizeof is an unevaluated operand and thus matches the third bullet.