I'm reading the copy elision section of a C++ reference guide, especially the paragraph about unnamed return value optimization (URVO). It says that constructing a temporary directly into its destination was allowed before C++17, and then labels that explanation "until C++17." Does this mean the behavior worked in C++98, C++11, and C++14 but stopped working in C++17? Or is the wording simply describing how the rules worked before C++17?
3 Answers
Before C++17, the compiler was generally allowed to remove certain temporary copies or moves, but the operation was technically optional. Since C++17, prvalue semantics make guaranteed elision possible in cases such as `T value = T();`, even when `T` has deleted copy and move constructors. Older programs do not suddenly become invalid just because you compile them as C++17.
It doesn’t mean the feature stopped working in C++17. “Until C++17” means that paragraph describes the rules before C++17. Starting with C++17, the language rules were rewritten and some cases that previously allowed copy elision became guaranteed instead. The result still works—and in some cases it is even more strongly guaranteed.
For example, consider `Widget make() { return Widget{}; }` followed by `Widget item = make();`. Before C++17, the compiler could construct the temporary directly as `item`, but it was also describing this as an elision of copies that might otherwise occur. Since C++17, the temporary prvalue is used to initialize the final object directly, so the copy or move is guaranteed away in this case.
This differs from returning a named local such as `Widget w; return w;`. Named return value optimization is still optional, so the compiler may need an accessible move or copy constructor there.

The labels can be confusing at first. They mark which version of the standard a particular explanation applies to, not the version in which the behavior disappears.