Is it possible to write C++ code where we rely on the return value optimization (RVO) when possible, but fall back on move semantics when not? For example, the following code c
When the expression in the return statement is a non-volatile automatic duration object, and not a function or catch-clause parameter, with the same cv-unqualified type as the function return type, the resulting copy/move is eligible for copy elision. The standard also goes on to say that, if the only reason copy elision was forbidden was that the source object was a function parameter, and if the compiler is unable to elide a copy, the overload resolution for the copy should be done as if the expression was an rvalue. Thus, it would prefer the move constructor.
OTOH, since you are using the ternary expression, none of the conditions hold and you are stuck with a regular copy. Changing your code to
if(b)
return x;
return y;
calls the move constructor.
Note that there is a distinction between RVO and copy elision - copy elision is what the standard allows, while RVO is a technique commonly used to elide copies in a subset of the cases where the standard allows copy elision.
Yes, there is. Don't return the result of a ternary operator; use if
/else
instead. When you return a local variable directly, move semantics are used when possible. However, in your case you're not returning a local directly -- you're returning the result of an expression.
If you change your function to read like this:
Foo f(bool b) {
Foo x;
Foo y;
if (b) { return x; }
return y;
}
Then you should note that your move constructor is called instead of your copy constructor.
If you stick to returning a single local value per return statement then move semantics will be used if supported by the type.
If you don't like this approach then I would suggest that you stick with std::move
. You may not like it, but you have to pick your poison -- the language is the way that it is.