In many cases, I would like to create a new instance of data and return it to the API caller.
I learned that unique_ptr/shared_ptr can be used for factory pattern (for example, Factory pattern using unique_ptr in c++)
At the same time, I learned that returned value optimization (RVO) is possible in many compilers (for example, Efficient way to return a std::vector in c++).
I prefer RVO since it is easier to use the returned value without a wrapping unique_ptr and easier to read the code, however, since the RVO is not guaranteed, I don't want to sacrifice performance unexpectedly and have to use unique_ptr to ensure returned value is moved instead of copied.
Is there any approach that I can explicitly specify the return value to be moved, so that either it will not complain anything if RVO is possible or it will trigger some compiler warning if RVO is not possible? If this is possible, I can safely get rid of returning a unique_ptr in this case.
I am using C++17 and need to support Apple Clang 11.0 on macOS and g++ 9 on Linux.
Edited:
I am still learning C++ and didn't make distinction between RVO (Return Value Optimization) and NRVO (Named Return Value Optimization) when posting this question. It seems to me NRVO is more common and useful in patterns like factory method, for example:
vector<foo> vec;
// populate data into vec
return vec;
And I am looking for something like a return std::move_only(returned_value) that will give me a compiler warning if this value cannot be moved (not copy to move).
Maybe I should re-phrase my question as: if NRVO is not guaranteed, why "return by value" is still the recommended way in this question (Efficient way to return a std::vector in c++), shouldn't the answer be "it depends" on your function implementation and whether or not you could accept unexpected performance cost?
You cannot return a unique_ptr without either RVO, NRVO, or implicit move in case NRVO isn't possible. It's not copyable:
This does not compile. If it weren't for RVO, NRVO or move, this wouldn't compile either:
In this case, this is due to C++17's guaranteed RVO. But even if there was no RVO, you'd still get a move instead of a copy.
And if it weren't for NRVO or guaranteed move fallback, this wouldn't compile:
So you are already depending on RVO, NRVO or moves. No need for unique_ptr. If your types are movable, you can be sure no copies are performed even in cases where NRVO isn't possible, like when not all
returnstatements return the same local object: