The following compiles without error:
#include
std::unique_ptr f() {
std::unique_ptr x(new int(42));
return x;
I thought that the return value of
f()
was copy-initialized byx
, butstd::unique_ptr
is a move-only type
The return value of f()
is indeed copy-initialized from the expression x
, but copy-initialization does not always imply copy-construction. If the expression is an rvalue, then the move constructor will be picked by overload resolution (assuming a move constructor is present).
Now although it is true that the expression x
in the return x;
statement is an lvalue (which may lead you to think that what I just wrote does not apply), in situations where a named object with automatic storage duration is returned, the compiler shall first try to treat the id-expression as an rvalue for overload resolution.
What is the relevant clause in the standard? Is there somewhere that says if
f()
is a move-only type than areturn
statement becomes a move construction instead of a copy construction?
Per paragraph 12.8/32 of the C++ Standard ([class.copy]/32, draft N4296):
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a
return
statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. [...]