Trivia impact: real
The Object That Cannot Be Moved
deleted copy and move constructors, yet a returned object
struct Locked {
Locked() { std::cout << "made\n"; }
Locked(const Locked&) = delete;
Locked(Locked&&) = delete;
};
Locked make() {
return Locked{};
}
Locked value = make();
Can a factory return an object that cannot be copied or moved?
Why¶
In C++17, the prvalue Locked{} directly initializes the result object of make, and
that result directly initializes value. [dcl.init.general] makes those prvalue
initializations guaranteed — "if the initializer expression is a prvalue and the
cv-unqualified version of the source type is the same as the destination type, the
initializer expression is used to initialize the destination object" — so no copy or move
constructor is selected at either step. This is not the optional elision of
[class.copy.elision]: returning a named local still relies on an optimization the
compiler is permitted, but never required, to perform.
Where it shows up¶
Factories can naturally return non-copyable resources, including types that contain a mutex. The C++17 rule removes a formerly common reason to add a move constructor solely to make a direct prvalue return compile.
Takeaway: A C++17 prvalue can initialize its destination without a copy or move.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo