C++ Logo

std-discussion

Advanced search

Are deleted copy/move operations trivial or non-trivial?

From: Stephan Bergmann <sbergman_at_[hidden]>
Date: Tue, 21 Jun 2022 13:22:59 +0200
What motivated me to ask this question is the discussion starting in the
comments at <https://reviews.llvm.org/D127593#3596601> "[clang] Fix
trivially copyable for copy constructor and copy assignment operator":

Consider
> struct S1 {};
> struct S2: S1 {
> S2(S2 &) = delete;
> };
with a deleted copy constructor for S2.

For default constructors and for destructors, the respective definitions
of triviality are worded in such a way that it apparently makes no
difference whether or not the given con-/destructor is deleted:

[class.default.ctor]/3:
> A default constructor is trivial if it is not user-provided and if:
> — its class has no virtual functions (11.7.2) and no virtual base
> classes (11.7.1), and
> — no non-static data member of its class has a default member
> initializer (11.4), and
> — all the direct base classes of its class have trivial default
> constructors, and
> — for all the non-static data members of its class that are of class
> type (or array thereof), each such class has a trivial default
> constructor.
> Otherwise, the default constructor is non-trivial.

[class.dtor]/8:
> A destructor is trivial if it is not user-provided and if:
> — the destructor is not virtual,
> — all of the direct base classes of its class have trivial destructors,
> and
> — for all of the non-static data members of its class that are of class
> type (or array thereof), each such class has a trivial destructor.
> Otherwise, the destructor is non-trivial.

But for copy/move constructors and for copy/move assignment operators
(for which I use the collective term "copy/move operation" here) the
situation appears to be less clear:

[class.copy.ctor]/11:
> A copy/move constructor for class X is trivial if it is not
> user-provided and if:
> — class X has no virtual functions (11.7.2) and no virtual base classes
> (11.7.1), and
> — the constructor selected to copy/move each direct base class subobject
> is trivial, and
> — for each non-static data member of X that is of class type (or array
> thereof), the constructor selected to copy/move that member is trivial;
> otherwise the copy/move constructor is non-trivial.

[class.copy.assign]/9:
> A copy/move assignment operator for class X is trivial if it is not
> user-provided and if:
> — class X has no virtual functions (11.7.2) and no virtual base classes
> (11.7.1), and
> — the assignment operator selected to copy/move each direct base class
> subobject is trivial, and
> — for each non-static data member of X that is of class type (or array
> thereof), the assignment operator selected to copy/move that member is
> trivial;
> otherwise the copy/move assignment operator is non-trivial.

Both of the above definitions of triviality delegate to something that
is "selected to copy/move" certain subobjects. But if the copy/move
operation is deleted, nothing actually gets selected. That IMO gives
rise to two potential interpretations: On the one hand, as nothing gets
selected, it is irrelevant whether what would be selected if the
copy/move operation were not deleted is trivial (and thus the deleted
copy constructor of S2 is trivial). On the other hand, as nothing gets
selected, the requirement that what gets selected is trivial is not met
(and thus the deleted copy constructor of S2 is non-trivial, as no
trivial constructor is selected to copy the S1 base class subobject).

(Not sure whether this question makes a practical difference for the
standard though, as qualification of (non-)triviality of such copy/move
operations appears to generally by accompanied by some non-deletedness
qualification.)

Received on 2022-06-21 11:23:04