[diff.cpp20] # Annex C (informative) Compatibility [[diff]](./#diff) ## C.2 C++ and ISO C++ 2020 [diff.cpp20] ### [C.2.1](#general) General [[diff.cpp20.general]](diff.cpp20.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L461) Subclause [diff.cpp20] lists the differences between C++ and ISO C++ 2020, in addition to those listed above, by the chapters of this document[.](#general-1.sentence-1) ### [C.2.2](#lex) [[lex]](lex "5 Lexical conventions"): lexical conventions [[diff.cpp20.lex]](diff.cpp20.lex) [1](#lex-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L470) **Affected subclause:** [[lex.name]](lex.name) **Change:** Previously valid identifiers containing characters not present in UAX #44 properties XID_Start or XID_Continue, or not in Normalization Form C, are now rejected[.](#lex-1.sentence-1) **Rationale:** Prevent confusing characters in identifiers[.](#lex-1.sentence-2) Requiring normalization of names ensures consistent linker behavior[.](#lex-1.sentence-3) **Effect on original feature:** Some identifiers are no longer well-formed[.](#lex-1.sentence-4) [2](#lex-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L483) **Affected subclause:** [[lex.string]](lex.string) **Change:** Concatenated [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* can no longer have conflicting [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3 Character literals [lex.ccon]")es[.](#lex-2.sentence-1) **Rationale:** Removal of unimplemented conditionally-supported feature[.](#lex-2.sentence-2) **Effect on original feature:** Concatenation of [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* with different [*encoding-prefix*](lex.ccon#nt:encoding-prefix "5.13.3 Character literals [lex.ccon]")es is now ill-formed[.](#lex-2.sentence-3) [*Example [1](#lex-example-1)*: auto c = L"a" U"b"; // was conditionally-supported; now ill-formed — *end example*] ### [C.2.3](#expr) [[expr]](expr "7 Expressions"): expressions [[diff.cpp20.expr]](diff.cpp20.expr) [1](#expr-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L501) **Affected subclause:** [[expr.prim.id.unqual]](expr.prim.id.unqual) **Change:** Change move-eligible [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")*s* from lvalues to xvalues[.](#expr-1.sentence-1) **Rationale:** Simplify the rules for implicit move[.](#expr-1.sentence-2) **Effect on original feature:** Valid C++ 2020 code that relies on a returned [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")'s being an lvalue may change behavior or fail to compile[.](#expr-1.sentence-3) [*Example [1](#expr-example-1)*: decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int&int& g(int&& x) { return x; } // ill-formed; previously well-formed — *end example*] [2](#expr-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L516) **Affected subclause:** [[expr.sub]](expr.sub) **Change:** Change the meaning of comma in subscript expressions[.](#expr-2.sentence-1) **Rationale:** Enable repurposing a deprecated syntax to support multidimensional indexing[.](#expr-2.sentence-2) **Effect on original feature:** Valid C++ 2020 code that uses a comma expression within a subscript expression may fail to compile[.](#expr-2.sentence-3) [*Example [2](#expr-example-2)*: arr[1, 2] // was equivalent to arr[(1, 2)],// now equivalent to arr.operator[](1, 2) or ill-formed — *end example*] ### [C.2.4](#stmt) [[stmt]](stmt "8 Statements"): statements [[diff.cpp20.stmt]](diff.cpp20.stmt) [1](#stmt-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L533) **Affected subclause:** [[stmt.ranged]](stmt.ranged) **Change:** The lifetime of temporary objects in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") is extended until the end of the loop ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#stmt-1.sentence-1) **Rationale:** Improve usability of the range-based for statement[.](#stmt-1.sentence-2) **Effect on original feature:** Destructors of some temporary objects are invoked later[.](#stmt-1.sentence-3) [*Example [1](#stmt-example-1)*: void f() { std::vector v = { 42, 17, 13 }; std::mutex m; for (int x :static_cast(std::lock_guard(m)), v) { // lock released in C++ 2020 std::lock_guard guard(m); // OK in C++ 2020, now deadlocks}} — *end example*] ### [C.2.5](#dcl) [[dcl]](dcl "9 Declarations"): declarations [[diff.cpp20.dcl]](diff.cpp20.dcl) [1](#dcl-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L557) **Affected subclause:** [[dcl.init.string]](dcl.init.string) **Change:** UTF-8 string literals may initialize arrays of char orunsigned char[.](#dcl-1.sentence-1) **Rationale:** Compatibility with previously written code that conformed to previous versions of this document[.](#dcl-1.sentence-2) **Effect on original feature:** Arrays of char or unsigned char may now be initialized with a UTF-8 string literal[.](#dcl-1.sentence-3) This can affect initialization that includes arrays that are directly initialized within class types, typically aggregates[.](#dcl-1.sentence-4) [*Example [1](#dcl-example-1)*: struct A {char8_t s[10];};struct B {char s[10];}; void f(A);void f(B); int main() { f({u8""}); // ambiguous} — *end example*] ### [C.2.6](#temp) [[temp]](temp "13 Templates"): templates [[diff.cpp20.temp]](diff.cpp20.temp) [1](#temp-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L588) **Affected subclause:** [[temp.deduct.type]](temp.deduct.type) **Change:** Deducing template arguments from exception specifications[.](#temp-1.sentence-1) **Rationale:** Facilitate generic handling of throwing and non-throwing functions[.](#temp-1.sentence-2) **Effect on original feature:** Valid ISO C++ 2020 code may be ill-formed in this revision of C++[.](#temp-1.sentence-3) [*Example [1](#temp-example-1)*: template struct A { };template void f(void (*)(A) noexcept(B));void g(A) noexcept;void h() { f(g); // ill-formed; previously well-formed} — *end example*] ### [C.2.7](#library) [[library]](library "16 Library introduction"): library introduction [[diff.cpp20.library]](diff.cpp20.library) [1](#library-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L608) **Affected subclause:** [[headers]](headers) **Change:** New headers[.](#library-1.sentence-1) **Rationale:** New functionality[.](#library-1.sentence-2) **Effect on original feature:** The following C++ headers are new:[](expected.syn#header:%3cexpected%3e "22.8.2 Header synopsis [expected.syn]"),[](flat.map.syn#header:%3cflat_map%3e "23.6.7 Header synopsis [flat.map.syn]"),[](flat.set.syn#header:%3cflat_set%3e "23.6.10 Header synopsis [flat.set.syn]"),[](generator.syn#header:%3cgenerator%3e "25.8.2 Header synopsis [generator.syn]"),[](mdspan.syn#header:%3cmdspan%3e "23.7.3.2 Header synopsis [mdspan.syn]"),[](print.syn#header:%3cprint%3e "31.7.4 Header synopsis [print.syn]"),[](span.streams.overview#header:%3cspanstream%3e "31.9.1 Overview [span.streams.overview]"),[](stacktrace.syn#header:%3cstacktrace%3e "19.6.2 Header synopsis [stacktrace.syn]"),[](stdatomic.h.syn#header:%3cstdatomic.h%3e "32.5.12 C compatibility [stdatomic.h.syn]"), and[](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header synopsis [stdfloat.syn]")[.](#library-1.sentence-3) Valid C++ 2020 code that #includes headers with these names may be invalid in this revision of C++[.](#library-1.sentence-4) ### [C.2.8](#concepts) [[concepts]](concepts "18 Concepts library"): concepts library [[diff.cpp20.concepts]](diff.cpp20.concepts) [1](#concepts-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L630) **Affected subclauses:** [[cmp.concept]](cmp.concept), [[concept.equalitycomparable]](concept.equalitycomparable), and [[concept.totallyordered]](concept.totallyordered) **Change:** Replace common_reference_with in three_way_comparable_with,equality_comparable_with, and totally_ordered_with with an exposition-only concept[.](#concepts-1.sentence-1) **Rationale:** Allow uncopyable, but movable, types to model these concepts[.](#concepts-1.sentence-2) **Effect on original feature:** Valid C++ 2020 code relying on subsumption with common_reference_with may fail to compile in this revision of C++[.](#concepts-1.sentence-3) [*Example [1](#concepts-example-1)*: templaterequires [equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")bool attempted_equals(const T&, const U& u); // previously selected overloadtemplaterequires [common_reference_with](concept.commonref#concept:common_reference_with "18.4.5 Concept common_­reference_­with [concept.commonref]")&, const remove_reference_t&>bool attempted_equals(const T& t, const U& u); // ambiguous overload; previously// rejected by partial orderingbool test(shared_ptr p) {return attempted_equals(p, nullptr); // ill-formed; previously well-formed} — *end example*] ### [C.2.9](#memory) [[mem]](mem "20 Memory management library"): memory management library [[diff.cpp20.memory]](diff.cpp20.memory) [1](#memory-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L659) **Affected subclause:** [[allocator.traits.general]](allocator.traits.general) **Change:** Forbid partial and explicit program-defined specializations of allocator_traits[.](#memory-1.sentence-1) **Rationale:** Allow addition of allocate_at_least to allocator_traits, and potentially other members in the future[.](#memory-1.sentence-2) **Effect on original feature:** Valid C++ 2020 code that partially or explicitly specializes allocator_traits is ill-formed with no diagnostic required in this revision of C++[.](#memory-1.sentence-3) ### [C.2.10](#utilities) [[utilities]](utilities "22 General utilities library"): general utilities library [[diff.cpp20.utilities]](diff.cpp20.utilities) [1](#utilities-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L673) **Affected subclause:** [[format]](format) **Change:** Signature changes: format, format_to, vformat_to,format_to_n, formatted_size[.](#utilities-1.sentence-1) Removal of format_args_t[.](#utilities-1.sentence-2) **Rationale:** Improve safety via compile-time format string checks, avoid unnecessary template instantiations[.](#utilities-1.sentence-3) **Effect on original feature:** Valid C++ 2020 code that contained errors in format strings or relied on previous format string signatures orformat_args_t may become ill-formed[.](#utilities-1.sentence-4) [*Example [1](#utilities-example-1)*: auto s = std::format("{:d}", "I am not a number"); // ill-formed,// previously threw format_error — *end example*] [2](#utilities-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L693) **Affected subclause:** [[format]](format) **Change:** Signature changes: format, format_to, format_to_n,formatted_size[.](#utilities-2.sentence-1) **Rationale:** Enable formatting of views that do not support iteration when const-qualified and that are not copyable[.](#utilities-2.sentence-2) **Effect on original feature:** Valid C++ 2020 code that passes bit-fields to formatting functions may become ill-formed[.](#utilities-2.sentence-3) [*Example [2](#utilities-example-2)*: struct tiny {int bit: 1;}; auto t = tiny(); std::format("{}", t.bit); // ill-formed, previously returned "0" — *end example*] [3](#utilities-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L715) **Affected subclause:** [[format.string.std]](format.string.std) **Change:** Restrict types of formatting arguments used as *width* or *precision* in a *std-format-spec*[.](#utilities-3.sentence-1) **Rationale:** Disallow types that do not have useful or portable semantics as a formatting width or precision[.](#utilities-3.sentence-2) **Effect on original feature:** Valid C++ 2020 code that passes a boolean or character type as*arg-id* becomes invalid[.](#utilities-3.sentence-3) [*Example [3](#utilities-example-3)*: std::format("{:*^{}}", "", true); // ill-formed, previously returned "*" std::format("{:*^{}}", "", '1'); // ill-formed, previously returned an// implementation-defined number of '*' characters — *end example*] [4](#utilities-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L734) **Affected subclause:** [[format.formatter.spec]](format.formatter.spec) **Change:** Removed the formatter specialization:template struct formatter; **Rationale:** The specialization is inconsistent with the design of formatter, which is intended to be instantiated only with cv-unqualified object types[.](#utilities-4.sentence-2) **Effect on original feature:** Valid C++ 2020 code that instantiated the removed specialization can become ill-formed[.](#utilities-4.sentence-3) ### [C.2.11](#strings) [[strings]](strings "27 Strings library"): strings library [[diff.cpp20.strings]](diff.cpp20.strings) [1](#strings-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L749) **Affected subclause:** [[string.classes]](string.classes) **Change:** Additional rvalue overload for the substr member function and the corresponding constructor[.](#strings-1.sentence-1) **Rationale:** Improve efficiency of operations on rvalues[.](#strings-1.sentence-2) **Effect on original feature:** Valid C++ 2020 code that created a substring by calling substr (or the corresponding constructor) on an xvalue expression with type S that is a specialization of basic_string may change meaning in this revision of C++[.](#strings-1.sentence-3) [*Example [1](#strings-example-1)*: std::string s1 = "some long string that forces allocation", s2 = s1; std::move(s1).substr(10, 5); assert(s1 == s2); // unspecified, previously guaranteed to be true std::string s3(std::move(s2), 10, 5); assert(s1 == s2); // unspecified, previously guaranteed to be true — *end example*] ### [C.2.12](#containers) [[containers]](containers "23 Containers library"): containers library [[diff.cpp20.containers]](diff.cpp20.containers) [1](#containers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L773) **Affected subclauses:** [[associative.reqmts]](associative.reqmts) and [[unord.req]](unord.req) **Change:** Heterogeneous extract and erase overloads for associative containers[.](#containers-1.sentence-1) **Rationale:** Improve efficiency of erasing elements from associative containers[.](#containers-1.sentence-2) **Effect on original feature:** Valid C++ 2020 code may fail to compile in this revision of C++[.](#containers-1.sentence-3) [*Example [1](#containers-example-1)*: struct B {auto operator<=>(const B&) const = default;}; struct D : private B {void f(std::set>& s) { s.erase(*this); // ill-formed; previously well-formed}}; — *end example*] ### [C.2.13](#thread) [[thread]](thread "32 Concurrency support library"): concurrency support library [[diff.cpp20.thread]](diff.cpp20.thread) [1](#thread-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L797) **Affected subclause:** [[thread.barrier]](thread.barrier) **Change:** In this revision of C++, it is implementation-defined whether a barrier's phase completion step runs if no thread calls wait[.](#thread-1.sentence-1) Previously the phase completion step was guaranteed to run on the last thread that calls arrive or arrive_and_drop during the phase[.](#thread-1.sentence-2) In this revision of C++, it can run on any of the threads that arrived or waited at the barrier during the phase[.](#thread-1.sentence-3) **Rationale:** Correct contradictory wording and improve implementation flexibility for performance[.](#thread-1.sentence-4) **Effect on original feature:** Valid C++ 2020 code using a barrier might have different semantics in this revision of C++ if it depends on a completion function's side effects occurring exactly once, on a specific thread running the phase completion step, or on a completion function's side effects occurring without wait having been called[.](#thread-1.sentence-5) [*Example [1](#thread-example-1)*: auto b0 = std::barrier(1); b0.arrive(); b0.arrive(); // implementation-defined; previously well-definedint data = 0;auto b1 = std::barrier(1, [&] { data++; }); b1.arrive(); assert(data == 1); // implementation-defined; previously well-defined b1.arrive(); // implementation-defined; previously well-defined — *end example*]