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).