3

From the standard 6.7.7 (temporary objects), we can see:

When an object of class type X is passed to or returned from a function, if X has at least one eligible copy or move constructor ([special]), each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object. The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). [Note 4: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. — end note]

Does it mean that copy elision is not mandatory with trivially copyable types? What I understand here is that if we declare a destructor like ~Object() {} instead of not declaring anything (so the destructor would be generated by the compiler) or a default one, the object becomes not trivially constructible, and so, the copy elision must be performed (at the condition we respect the well-known condition for copy elision to occur).

Antoine Morrier
  • 3,930
  • 16
  • 37
  • 1
    You're going to need to be more precise in how you've tagged the question, and which release (or draft) of the C++ standard you are referring to. Tagging "C++17" implies the 2017 standard, and that standard does not have a section 6.7.7 at all (let alone one with a heading about temporary objects). – Peter May 04 '21 at 09:18
  • 1
    But it does have **[class.temporary]** which is 6.7.7 in C++20 and 15.2 in C++17. Which is why, OP, you should prefer the *stable* section designators. – StoryTeller - Unslander Monica May 04 '21 at 09:33

1 Answers1

4

Does it mean that copy elision is not mandatory with trivially copyable types?

In principle, yes, but the goal of the section you quoted was not to exempt POD types from copy elision but to bypass ABI restrictions on how objects are passed in function calls. It allows POD objects to be passed via registers. This is the best the standard can do given the C++ abstract machine knows nothing about the physical machine and its registers and calling conventions.

Guaranteed copy elision is a result of several changes spread throughout the standard, which includes deferred prvalue materialization. For details refer to the original proposal p0135r1.

With those changes it becomes possible (and required) to initialize an object without involving temporaries ([dcl.init.general]/15.6.1):

— Otherwise, if the destination type is a (possibly cv-qualified) class type:

  • If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.
rustyx
  • 80,671
  • 25
  • 200
  • 267