When performing copy-elision, the compiler does not consider the copy constructor in overload resolution when the move constructor is deleted. What for?

I understand that the compiler does the copying in the code below, since copy and move constructors are not called in the so-called copy-initialization done in main() . See a live example .

 #include <iostream> struct S { S() = default; S(const S&) { std::cout << "copy ctor" << '\n'; } S(S&&) { std::cout << "move ctor" << '\n'; } }; int main() { S s = S(); } 

But I cannot understand why the code does not compile when I remove the move constructor, as shown below:

 #include <iostream> struct S { S() = default; S(const S&) { std::cout << "copy ctor" << '\n'; } S(S&&) = delete; }; int main() { S s = S(); } 

I cannot find anything in §12.8 / 32 (N4140), which could prohibit the use of a constructor in this case. This proposal, which aroused my attention in § 12.8 / 32, which seems to indicate that the copy constructor should have been considered in overload resolution:

If the first overload resolution failed or was not executed, or if the type of the first parameter of the selected constructor is not rvalue refers to the type of objects (possibly cv-qualit), overload resolution is performed again, treating the object as naming.

Edit

From one of TC's comments below, I understand that when the object to be copied is denoted by rvalue, the compiler, according to §12.8 / 32, does not consider the copy-instance as a candidate for the copy, although the copy will be rejected anyway. That is, the end result will be the construction of an object s with a standard constructor. Instead, in this situation, the standard requires (where?) A badly formed code. If my understanding of this scheme is completely wrong, it makes no sense to me.

+5
source share
1 answer

This has nothing to do with copies or constructors; this is just permission to overload.

If we have a couple of overloads:

 void f( T&& rv ); void f( const T& lv ); 

then overload resolution rules say that f( T{} ) better suited for f(T&&) .

Copying elision can speed up copying or moving, but only if the code is correctly defined (even if the compiler decided not to copy). Your code is undefined because it indicates a call to a remote function.

+1
source

All Articles