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?