Should we write `std::move` in the cases when RVO can not be done?

Solution 1:

What happen in your example is not linked to RVO, but to the ternary operator ?. If you rewrite your example code using an if statement, the behavior of the program will be the one expected. Change foo definition to:

Test foo(int param)
  {
  Test test1;
  Test test2;
  if (param > 5)
    return std::move(test2);
  else
    return test1;
  }

will output Test(Test&&).


What happens if you write (param>5)?std::move(test1):test2 is:

  1. The ternary operator result is deduced to be a prvalue [expr.cond]/5
  2. Then test2 pass through lvalue-to-rvalue conversion which causes copy-initialization as required in [expr.cond]/6
  3. Then the move construction of the return value is elided [class.copy]/31.3

So in your example code, move elision occurs, nevertheless after the copy-initialization required to form the result of the ternary operator.