with your design:
void doWork(Widget && param)
{
Widget store1 = param; // automatically move param
Widget store2 = param; // boom
Widget store_last = param; // boom
}
with current design:
void doWork(Widget && param)
{
Widget store1 = param; // ok, copy
Widget store2 = param; // ok, copy
Widget store_last = std::move(param); // ok, param is moved at its last use
}
So the moral here is that even if you have an rvalue reference you have a name for it which means you can use it multiple times. As such you can't automatically move it because you could need it for a later use.
Now let's say you want to re-design the language so that the last use is automatically treated as an rvalue.
This can be easily done in the above example:
void doWork(Widget && param)
{
Widget store1 = param; // `param` treated as lvalue here, copy
Widget store2 = param; // `param` treated as lvalue here, copy
Widget store_last = param; // `param` treated as rvalue here, move
}
Let's ignore the inconsistency of how param
is treated (which in itself is a problem).
Now think what use of param
is the last use:
void doWork(Widget && param)
{
Widget store2 = param; // this can be last use or not
while (some_condition())
{
Widget store1 = param; // this can be both last use and not
}
}
The language simply cannot be designed this way.