This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
Consider:
#include<new> struct A { ~A(); }; union U { alignas(A) unsigned char buf[sizeof(A)]; }; void f() { U u; ::new (u.buf) A(); // object of type A is nested within u because u provides storage U v = u; // #1 }
Subclause 11.4.5.3 [class.copy.ctor] paragraph 15 specifies:
The implicitly-defined copy/move constructor for a union X copies the object representation (6.8.1 [basic.types.general]) of X. For each object nested within (6.7.2 [intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is identified (if the object is a subobject) or created (otherwise), and the lifetime of o begins before the copy is performed.
Thus, the rule seems to require that #1 creates an object of type A inside v.buf (without invoking a constructor of A), and then a copy of the object representation is performed. Creating an object out of thin air can plausibly work only for implicit-lifetime types (11.2 [class.prop] paragraph 9), and meaningfully copying the object representation works only for trivially copyable types (6.8.1 [basic.types.general] paragraph 3). The rule about nested objects should be suitably limited.
Subclause 11.4.6 [class.copy.assign] paragraph 13 has a similar rule for copy/move assignment:
The implicitly-defined copy/move assignment operator for a union X copies the object representation (6.8.1 [basic.types.general]) of X. If the source and destination of the assignment are not the same object, then for each object nested within (6.7.2 [intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is created, and the lifetime of o begins before the copy is performed.
Possible resolution:
Change in 11.4.5.3 [class.copy.ctor] paragraph 15 as follows:
The implicitly-defined copy/move constructor for a union X copies the object representation (6.8.1 [basic.types.general]) of X. For each object of implicit-lifetime type (6.8.1 [basic.types.general]) nested within (6.7.2 [intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is identified (if the object is a subobject) or created (otherwise), and the lifetime of o begins before the copy is performed.
Change in 11.4.6 [class.copy.assign] paragraph 13 as follows:
The implicitly-defined copy/move assignment operator for a union X copies the object representation (6.8.1 [basic.types.general]) of X. If the source and destination of the assignment are not the same object, then for each object of implicit-lifetime type (6.8.1 [basic.types.general]) nested within (6.7.2 [intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is created, and the lifetime of o begins before the copy is performed.