Description
Full name of submitter: Brian Bi
Issue description: The allowance in [class.mem.general]/29 to read from a member of the common initial sequence of an inactive union member with the active member should be clarified. It is probably intended to apply only to cases where both the inactive union member and its member are explicitly named, as opposed to being accessed through a pointer, reference, or pointer-to-member.
Suggested resolution: Edit [class.mem.general]/29:
In a standard-layout union with an active member of struct type T1, it is permitted to read a non-static data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2; the behavior is as if the corresponding member of T1 were nominated.Except during the evaluation of an expression as a core constant expression ([expr.const]), when an lvalue-to-rvalue conversion ([conv.lval]) is applied to an expression of the form u.
s.
m O1 ... On where u is possibly the result of an implicit transformation ([expr.ref], [expr.prim.id.general]), n is possibly zero, and
- u is of union type and has an active member,
- s designates an inactive member of u having standard-layout struct type,
- m designates a member of the common initial sequence of s's type and the type of u's active member, and
- each element of O has the form
.
identifier where the identifier designates a non-static data member or[
expression]
where the left operand is of array typethe result is as if the active member were nominated instead of s, m were replaced by the name of the corresponding member of the active member's type, and for each element of O of the form
.
identifier, the identifier were replaced by the name of the corresponding member of the type that the left operand would have after all preceding replacements.
[Example 5: ... ]
[Example 5:
struct X { int x; };
struct Y { int y; };
struct T1 { X a[2]; };
struct T2 { Y b[2]; };
union U { T1 t1; T2 t2; };
int f() {
U u = {{{{0}, {1}}}}; // active member is t1
return u.t2.b[1].y; // OK, as if the operand were u.t1.a[1].x
}
— end example]