Why is "partial RVO" not performed?
Let's consider what happens if RVO is done for f
, meaning it is constructed directly in the return value. If first==true
and f
gets returned, great, no copy is needed. But if first==false
then s
gets returned instead, so the program will copy construct s
over the top of f
before the destructor for f
has run. Then after that, the destructor for f
will run, and now the return value is an invalid object that has already been destroyed!
If RVO is done for s
instead the same argument applies, except that now the problem happens when first==true
.
Whichever one you choose, you avoid a copy in 50% of cases and get undefined behaviour in the other 50% of cases! That's not a desirable optimization!
In order to make this work the order of destruction of the local variables would have to be altered so that f
is destroyed before copying s
into that memory location (or vice versa), and that's a very risky thing to mess with. The order of destruction is a fundamental property of C++ that should not be fiddled with, or you'll break RAII and who knows how many other assumptions.