RVO is dead. Long live RVO.
In modern C++, there are two cases corresponding to what used to be called RVO:
- There's NRVO, in which the compiler is allowed to elide a local variable if it can see that that variable will just be returned eventually. If the compiler declines to elide the local variable, then it is obligated to treat it as an rvalue when it is returned, assuming certain conditions are met (thus converting a copy into a move). This is not what your question is asking about.
- There's also guaranteed copy elision --- but to even use that name for it is to think about C++17 using a pre-C++17 mindset. What really changed in C++17 is that prvalues are no longer "objects without identity" but rather "recipes for creating objects". This is the reason why copy-elision-like behaviour is guaranteed.
So let's look at your statement:
T t=static_cast<T>(funcReturningT());
The expression funcReturningT()
is a prvalue. In C++14, this would mean that immediately upon evaluating it, the implementation would have to instantiate a temporary T
object (lacking identity), but non-guaranteed copy elision would allow the compiler (at its discretion) to elide such object. In C++17, it is ready to create a T
object but doesn't do so immediately.
Then the static_cast
is evaluated, and the result of it is also a prvalue of the same type. Because of this, no move constructor is required and no temporary object needs to be created. The result of the cast is just the original "recipe".
And finally, when t
is initialized from the result of the static_cast
, the move constructor is once again not required. The "recipe" that static_cast
used is simply executed with t
as the object that it creates.
The beauty of it is that there is nothing to elide, which is why "guaranteed copy elision" is a misnomer.
(Sometimes, temporary objects do need to be created: in particular, if any constructor or conversion function needs to be called at any point, then the prvalue has to be "materialized" in order for that call to actually have an object to work with. In your example, this is not necessary.)