My default behaviour for any objects in local scopes is to make it const. E.g.:
auto const cake = bake_cake(arguments);
I try to have as little non-functional code as I can as this increases readability (and offers some optimisation opportunities for the compiler). So it is logical to also reflect this in the type system.
However, with move semantics, this creates the problem: what if my cake is hard or impossible to copy and I want to pass it out after I'm done with it? E.g.:
if (tastes_fine(cake)) {
return serve_dish(cake);
}
As I understand copy elision rules it's not guaranteed that the cake copy will be elided (but I'm not sure on this).
So, I'd have to move cake out:
return serve_dish(std::move(cake)); // this will not work as intended
But that std::move will do nothing useful, as it (correctly) will not cast Cake const& to Cake&&. Even though the lifetime of the object is very near its end. We cannot steal resources from something we promised not to change. But this will weaken const-correctness.
So, how can I have my cake and eat it too?
(i.e. how can I have const-correctness and also benefit from move semantics.)