This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


2463. Trivial copyability and unions with non-trivial members

Section: 11.2  [class.prop]     Status: open     Submitter: Daveed Vandevoorde     Date: 2020-11-30     Liaison: EWG

According to 11.2 [class.prop] paragraph 1,

A trivially copyable class is a class:

This definition has surprising effects in a union whose members are not trivial. For example:

  struct S {
    S& operator=(const S&);
  };
  union U {
    S s;
  };

In this case, S is not trivially copyable because its assignment operator is non-trivial, although its copy constructor is trivial. U, however, is trivially copyable because its assignment operator is not eligible (11.4.4 [special] paragraph 6) because it is deleted, but its copy constructor is trivial, thus satisfying the second bullet.

It is unclear why, for example, a complete object of type S cannot be memcpyed but such an object can be memcpyed when embedded in a union.

There is implementation divergence in the handling of this example.

CWG 2022-11-10

Traditionally, the rule for trivial copyability has been that each of the potentially user-written ways of copying a class (copy/move constructors, copy/move assignment operators) have to be trivial (or deleted). See C++17 subclause 12p6:

A trivially copyable class is a class:

That seems unhelpful. The rule should instead be that if there is any way of copying the class such that the compiler will generate a memcpy (because the corresponding operation is trivial), the user should be allowed to perform memcpy, too. In terms of wording, this amounts to striking the first bullet and adding "trivial" to the second bullet. (The wording in the current working draft considers eligibility, which complicates the treatment slightly in terms unrelated to the present issue.)

CWG is seeking EWG advice on this issue via cplusplus/papers#1363.

Additional notes (March, 2023)

std::tuple with trivially-copyable element types and with no elements (std::tuple<>) ought to be trivially copyable, but the recent addition of const-qualified assignment operators makes that not so under the status quo core language rules.