Do all special member functions need to be trivial for a class to be trivially copyable?

153 Views Asked by At

The cppreference page for the named requirement of being TriviallyCopyable, in the subsection for classes, lists the following requirement:

Trivially copyable class

A trivially copyable class is a class that

  • has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator,
  • each eligible copy constructor is trivial
  • each eligible move constructor is trivial
  • each eligible copy assignment operator is trivial
  • each eligible move assignment operator is trivial, and
  • has a non-deleted trivial destructor.

so, if there's a trivial copy ctor but a non-trivial, say, move assignment operator - isn't the class trivially copyable? My intuition says that if you can construct an object of the same type by (trivially) memcpying the existing object (or assigning-by-memcpy to a constructed object) - that's trivial copyability.

2

There are 2 best solutions below

10
On BEST ANSWER

so, if there's a trivial copy ctor but a non-trivial, say, move assignment operator - isn't the class trivially copyable?

No, not if the copy constructor and move assignment operator are eligible, according to the C++23 standard:

11.2. Properties of classes [class.prop]

  1. A trivially copyable class is a class:

    1.1. — that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),

    1.2. — where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and

    1.3. — that has a trivial, non-deleted destructor ([class.dtor]).

  2. A trivial class is a class that is trivially copyable and has one or more eligible default constructors ([class.default.ctor]), all of which are trivial.

    [Note 1 : In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes. — end note]

11.4.4. Special member functions

  1. An eligible special member function is a special member function for which:

    6.1. the function is not deleted,

    6.2. the associated constraints, if any, are satisfied, and

    6.3. no special member function of the same kind is more constrained

5
On

The quote is correct. Each eligible copy/move operation must be trivial.

Trivial-copyability should mean that one is permitted to replace copying/moving of the object with memcpy without affecting semantics, and being allowed to use memcpy in this way is probably (originally) only for C compatibility as well. (Before C++11 split the POD concept, types were effectively required to be C types to be memcpyied at all.)

But if some of the special member functions are not trivial, that's not generally guaranteed.

For example if only the copy assignment, but not the move assignment, is trivial, then

X x{};
Y y;
y = std::move(x);

should not be permitted to be replaced by

X x{};
X y;
std::memcpy(&y, &x, sizeof(X));

because that skips potential side effects that the move assignment should have.

So, X is specified not to be trivially-copyable.

And in any case the memcpy above has UB, because the permission to memcpy object representation between objects like this is specified in terms of trivial-copyability as well. As mentioned above, I think the reason for this is that the permission exists (at least originally) purely for C compatibility. Types that have non-trivial copy/move operations aren't relevant for C compatibility.

Even if the requirements on copying object representation with memcpy were weaker, so that only one of the copy/move operations needs to be trivial, then having the trivially-copyable concept require only one operation to be trivial would still not be useful, because any library function using it would still need to check triviality of individual operations instead in order to use it for optimization.


All of the above being said, there seems to have been some discussion in the standard committee on this, see https://github.com/cplusplus/papers/issues/1363.