In the code below an object s
of class S
is used to initialize an object of class D
with a direct-initialization D d(s);
. The conversion function S::operator D() is used to convert the object s
into a temporary object of type D
. Then, gcc and clang both elide the explicit call to the move constructor D(&&)
, to move this temporary object into d
. See live example.
#include <iostream>
struct D;
struct S{ operator D(); };
struct D{
D(){}
D(D&&) { std::cout << "move constructor" << '\n'; }
};
S::operator D() { std::cout << "conversion function" << '\n'; return D(); }
int main()
{
S s;
D d(s);
}
I'm disputing the correctness of this elision, on the following grounds:
- This case is covered in the first sub-bullet point in ยง8.5/16 (N3337), which is silent about elision.
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.
- Note that the next sub-bullet point explicitly mentions the possibility of elision.
- The call to the move constructor is explicit. How can it be elided?
The C++ standard loves to create exceptions to rules defined in one place in a completely different place.
The copy/move elision rules are specified in 12.8/31. There are two copy/move operations to be eliminated in your code.
The first is easy: within
operator D
, the temporary constructed in the return expression is moved to the temporary that represents the function return value. Bullet 3 permits elision of this move.The second is the move of the temporary function return value to the
d
object. Again, bullet 3 permits the elision.