The C++17 change catalogue distinguishes new syntax from changed semantics
P0636R0 separates facilities programmers opt into from changes that affect existing expressions. Guaranteed copy elision shows why that distinction matters for interfaces returning objects by value.
A language upgrade can affect a program even when its source uses none of the new syntax. Thomas Köppe's April 2 P0636R0 catalogue separates C++17 changes with global applicability from facilities a programmer selects explicitly. Guaranteed copy elision belongs in the former group. It changes the model behind expressions that already look familiar.
The catalogue lists major changes made through dedicated papers between C++14 and the C++17 DIS, N4660. It explicitly excludes defect resolutions from the core and library issue lists. It is therefore a structured guide to major adopted work, not a claim to enumerate every semantic difference or compiler correction that a project might encounter.
I find that scope useful. C++ code already contains several generations of idiom, and a revision can change the meaning beneath an unchanged return statement. A catalogue that distinguishes such changes from optional new spellings gives a reader a better way to locate the rules that affect an interface.
A prvalue can initialize the destination directly
The copy-elision entry points to Richard Smith's P0135R1 wording. It recasts a prvalue as an expression that initializes a result object or computes an operand's value. The model no longer requires a chain of class temporaries whose intervening copies the optimizer may choose to omit.
That makes a difference for a type that cannot be copied or moved. A function returning a same-type prvalue can initialize its result directly under the new rules. The operation is permitted because the language does not require the missing transfer operation in that case.
struct token {
token() = default;
token(const token&) = delete;
token(token&&) = delete;
};
token make_token()
{
return token{};
}
token value = make_token();
This example relies on the C++17 semantics described by the adopted wording. It is not a request that an optimizer make a best-effort choice to rescue a program requiring an inaccessible copy. That distinction is the reason the catalogue describes guaranteed elision as affecting the language model.
The wording also introduces temporary materialization. When a context needs an object identity from a prvalue, a conversion initializes a temporary as the result object and produces an expression referring to it. The new model therefore does not abolish temporaries. It specifies when an object must be materialized instead of assuming every class prvalue begins as a separate temporary awaiting possible optimization.
Named return values remain a separate case
P0135R1 explicitly retains optional elision for named return-value optimization. Returning a local variable is different from returning the same-type prvalue in the example. The new guarantee should not be generalized into a promise that every return-by-value path avoids copy or move requirements.
That boundary matters when designing a factory for an immovable type. A declaration alone does not explain which return expressions its definition uses. The result's initialization model depends on those expressions, and a named local introduces a different case. Replacing every return with a broad statement about guaranteed elision would conceal the rule the implementation must satisfy.
The catalogue's separation of global and local changes helps here. A programmer can opt into structured bindings or an initializer in an if statement by writing their syntax. The prvalue change applies to ordinary existing initialization expressions once the program uses the newer language mode.
The wording also preserves requirements on the destruction of materialized class objects. Avoiding a copy operation does not mean an object can ignore its destructor's accessibility or deletion status. Lifetime responsibilities remain part of the model even when initialization no longer requires an intermediate transfer.
Other entries change interface requirements
Another globally applicable entry makes exception specifications part of function types. Köppe notes that this lets interfaces require non-throwing callbacks. It does not allow two otherwise identical function declarations to form an overload set solely because their exception specifications differ. The strengthened type rule still has limits on how declarations can differ.
The catalogue separately identifies dynamic allocation of over-aligned types and stricter expression evaluation rules. These concern existing operations whose behavior depends on the revised standard. Grouping them apart from new syntax directs attention to source that may already be present in a program.
New library vocabulary appears in its own section. string_view represents a non-owning view, while optional represents either a value or its absence. Those facilities are useful additions, but simply enabling the language mode does not rewrite existing application interfaces to use them. That is a deliberate code-design choice.
I prefer the catalogue as an entry point into the underlying papers. Its summaries locate the change, while the wording establishes the precise boundary. For copy elision, that boundary permits direct initialization from a same-type prvalue without a copy or move, and leaves named return-value elision optional. It is a concrete example of why a C++ revision needs to be read as a change to semantics as well as a collection of new declarations.