[diff.cpp23]

# Annex C (informative) Compatibility [[diff]](./#diff)

## C.1 C++ and ISO C++ 2023 [diff.cpp23]

### [C.1.1](#general) General [[diff.cpp23.general]](diff.cpp23.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L8)

Subclause [diff.cpp23] lists the differences between C++ and
ISO C++ 2023,
by the chapters of this document[.](#general-1.sentence-1)

### [C.1.2](#lex) [[lex]](lex "5 Lexical conventions"): lexical conventions [[diff.cpp23.lex]](diff.cpp23.lex)

[1](#lex-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L16)

**Affected subclause:** [[lex.operators]](lex.operators)  


**Change:** New operator ^^[.](#lex-1.sentence-1)

  


**Rationale:** Required for new features[.](#lex-1.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code that contains two consecutive ^ tokens
can be ill-formed in this revision of C++[.](#lex-1.sentence-3)

[*Example [1](#lex-example-1)*: struct C { int operator^(int); };int operator^(int (C::*p)(int), C);int i = &C::operator^^C{}; // ill-formed; previously well-formed â *end example*]

[2](#lex-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L32)

**Affected subclause:** [[lex.key]](lex.key)  


**Change:** New keywords[.](#lex-2.sentence-1)

  


**Rationale:** Required for new features[.](#lex-2.sentence-2)

- [(2.1)](#lex-2.1)

The contract_assert keyword
is added to introduce a contract assertion
through an [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]") ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion statement")).

  


**Effect on original feature:** Valid C++ 2023 code using contract_assert as an identifier
is not valid in this revision of C++[.](#lex-2.sentence-3)

### [C.1.3](#expr) [[expr]](expr "7 Expressions"): expressions [[diff.cpp23.expr]](diff.cpp23.expr)

[1](#expr-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L49)

**Affected subclause:** [[expr.arith.conv]](expr.arith.conv)  


**Change:** Operations mixing a value of an enumeration type and a value of a different
enumeration type or of a floating-point type are no longer valid[.](#expr-1.sentence-1)

  


**Rationale:** Reinforcing type safety[.](#expr-1.sentence-2)

  


**Effect on original feature:** A valid C++ 2023 program that performs operations mixing a value of an
enumeration type and a value of a different enumeration type or of a
floating-point type is ill-formed[.](#expr-1.sentence-3)

[*Example [1](#expr-example-1)*: enum E1 { e };enum E2 { f };bool b = e <= 3.7; // ill-formed; previously well-formedint k = f - e; // ill-formed; previously well-formedauto x = true ? e : f; // ill-formed; previously well-formed â *end example*]

[2](#expr-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L69)

**Affected subclauses:** [[expr.rel]](expr.rel) and [[expr.eq]](expr.eq)  


**Change:** Comparing two objects of array type is no longer valid[.](#expr-2.sentence-1)

  


**Rationale:** The old behavior was confusing since it compared not the contents of the two
arrays, but their addresses[.](#expr-2.sentence-2)

  


**Effect on original feature:** A valid C++ 2023 program directly comparing two array objects is rejected as
ill-formed in this document[.](#expr-2.sentence-3)

[*Example [2](#expr-example-2)*: int arr1[5];int arr2[5];bool same = arr1 == arr2; // ill-formed; previously well-formedbool idem = arr1 == +arr2; // compare addressesbool less = arr1 < +arr2; // compare addresses, unspecified result â *end example*]

[3](#expr-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L88)

**Affected subclause:** [[expr.delete]](expr.delete)  


**Change:** Calling delete on a pointer to an incomplete class is ill-formed[.](#expr-3.sentence-1)

  


**Rationale:** Reduce undefined behavior[.](#expr-3.sentence-2)

  


**Effect on original feature:** A valid C++ 2023 program that calls delete on an incomplete
class type is ill-formed[.](#expr-3.sentence-3)

[*Example [3](#expr-example-3)*: struct S;

void f(S *p) {delete p; // ill-formed; previously well-formed}struct S {}; â *end example*]

### [C.1.4](#dcl.dcl) [[dcl]](dcl "9 Declarations"): declarations [[diff.cpp23.dcl.dcl]](diff.cpp23.dcl.dcl)

[1](#dcl.dcl-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L110)

**Affected subclause:** [[dcl.decl.general]](dcl.decl.general)  


**Change:** Introduction of trivially_relocatable_if_eligible andreplaceable_if_eligible as identifiers with special meaning ([[lex.name]](lex.name "5.11 Identifiers"))[.](#dcl.dcl-1.sentence-1)

  


**Rationale:** Support declaration of trivially relocatable and replaceable types ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#dcl.dcl-1.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code can become ill-formed[.](#dcl.dcl-1.sentence-3)

[*Example [1](#dcl.dcl-example-1)*: struct C {};struct C replaceable_if_eligible {}; // was well-formed (new variable replaceable_if_eligible)// now ill-formed (redefines C) â *end example*]

[2](#dcl.dcl-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L126)

**Affected subclause:** [[dcl.init.list]](dcl.init.list)  


**Change:** Pointer comparisons between initializer_list objects' backing arrays
are unspecified[.](#dcl.dcl-2.sentence-1)

  


**Rationale:** Permit the implementation to store backing arrays in static read-only memory[.](#dcl.dcl-2.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code
that relies on the result of pointer comparison between backing arrays
may change behavior[.](#dcl.dcl-2.sentence-3)

[*Example [2](#dcl.dcl-example-2)*: bool ne(std::initializer_list<int> a, std::initializer_list<int> b) {return a.begin() != b.begin() + 1;}bool b = ne({2,3}, {1,2,3}); // unspecified result; previously false â *end example*]

[3](#dcl.dcl-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L145)

**Affected subclause:** [[dcl.array]](dcl.array)  


**Change:** Previously, T...[n] would declare a pack of function parameters[.](#dcl.dcl-3.sentence-1)

T...[n] is now a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")[.](#dcl.dcl-3.sentence-2)

  


**Rationale:** Improve the handling of packs[.](#dcl.dcl-3.sentence-3)

  


**Effect on original feature:** Valid C++ 2023 code that declares a pack of parameters
without specifying a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") becomes ill-formed[.](#dcl.dcl-3.sentence-4)

[*Example [3](#dcl.dcl-example-3)*: template <typename... T>void f(T... [1]);template <typename... T>void g(T... ptr[1]);int main() { f<int, double>(nullptr, nullptr); // ill-formed, previously void f<int, double>(int [1], double [1]) g<int, double>(nullptr, nullptr); // ok} â *end example*]

[4](#dcl.dcl-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L167)

**Affected subclause:** [[dcl.attr.grammar]](dcl.attr.grammar)  


**Change:** New token :][.](#dcl.dcl-4.sentence-1)

  


**Rationale:** Required for new features[.](#dcl.dcl-4.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code that contained an [*attribute-specifier*](dcl.attr.grammar#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with an [*attribute-using-prefix*](dcl.attr.grammar#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") but no attributes and no whitespace is ill-formed in this revision of C++[.](#dcl.dcl-4.sentence-3)

[*Example [4](#dcl.dcl-example-4)*: struct [[using CC:]] C; // ill-formed; previously well-formedstruct [[using DD: ]] D; // OK â *end example*]

### [C.1.5](#temp) [[temp]](temp "13 Templates"): templates [[diff.cpp23.temp]](diff.cpp23.temp)

[1](#temp-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L185)

**Affected subclause:** [[temp.constr]](temp.constr)  


**Change:** Some atomic constraints become fold expanded constraints[.](#temp-1.sentence-1)

  


**Rationale:** Permit the subsumption of fold expressions[.](#temp-1.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code may become ill-formed[.](#temp-1.sentence-3)

[*Example [1](#temp-example-1)*: template <typename ...V> struct A;struct S {static constexpr int compare(const S&) { return 1; }};

template <typename ...T, typename ...U>void f(A<T ...> *, A<U ...> *)requires (T::compare(U{}) && ...); // was well-formed (atomic constraint of type bool),// now ill-formed (results in an atomic constraint of type int)void g(A<S, S> *ap) { f(ap, ap);} â *end example*]

[2](#temp-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L209)

**Affected subclause:** [[temp.deduct.call]](temp.deduct.call)  


**Change:** Template argument deduction from overload sets succeeds in more cases[.](#temp-2.sentence-1)

  


**Rationale:** Allow consideration of constraints to disambiguate overload sets
used as parameters in function calls[.](#temp-2.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code may become ill-formed[.](#temp-2.sentence-3)

[*Example [2](#temp-example-2)*: template <typename T>void f(T &&, void (*)(T &&));

void g(int &); // #1inline namespace A {void g(short &&); // #2}inline namespace B {void g(short &&); // #3}void q() {int x;
 f(x, g); // ill-formed; previously well-formed, deducing T = int&}

There is no change to the applicable deduction rules for
the individual g candidates:
Type deduction from #1 does not succeed;
type deductions from #2 and #3 both succeed[.](#temp-2.sentence-4)

â *end example*]

### [C.1.6](#library) [[library]](library "16 Library introduction"): library introduction [[diff.cpp23.library]](diff.cpp23.library)

[1](#library-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L243)

**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:[<contracts>](contracts.syn#header:%3ccontracts%3e "17.10.1 Header <contracts> synopsis [contracts.syn]"),[<debugging>](debugging.syn#header:%3cdebugging%3e "19.7.2 Header <debugging> synopsis [debugging.syn]"),[<hazard_pointer>](hazard.pointer.syn#header:%3chazard_pointer%3e "32.11.3.2 Header <hazard_­pointer> synopsis [hazard.pointer.syn]"),[<hive>](hive.syn#header:%3chive%3e "23.3.8 Header <hive> synopsis [hive.syn]"),[<inplace_vector>](inplace.vector.syn#header:%3cinplace_vector%3e "23.3.15 Header <inplace_­vector> synopsis [inplace.vector.syn]"),[<linalg>](linalg.syn#header:%3clinalg%3e "29.9.2 Header <linalg> synopsis [linalg.syn]"),[<meta>](meta.syn#header:%3cmeta%3e "21.4.1 Header <meta> synopsis [meta.syn]"),[<rcu>](rcu.syn#header:%3crcu%3e "32.11.2.2 Header <rcu> synopsis [rcu.syn]"),[<simd>](simd.syn#header:%3csimd%3e "29.10.3 Header <simd> synopsis [simd.syn]"),[<stdbit.h>](stdbit.h.syn#header:%3cstdbit.h%3e "22.12 Header <stdbit.h> synopsis [stdbit.h.syn]"),[<stdckdint.h>](stdckdint.h.syn#header:%3cstdckdint.h%3e "29.11.1 Header <stdckdint.h> synopsis [stdckdint.h.syn]"), and[<text_encoding>](text.encoding.syn#header:%3ctext_encoding%3e "28.4.1 Header <text_­encoding> synopsis [text.encoding.syn]")[.](#library-1.sentence-3)

Valid C++ 2023 code that #includes headers with these names may be
invalid in this revision of C++[.](#library-1.sentence-4)

[2](#library-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L265)

**Affected subclause:** [[res.on.macro.definitions]](res.on.macro.definitions)  


**Change:** Additional restrictions on macro names[.](#library-2.sentence-1)

  


**Rationale:** Avoid hard to diagnose or non-portable constructs[.](#library-2.sentence-2)

  


**Effect on original feature:** Names of special identifiers may not be used as macro names[.](#library-2.sentence-3)

Valid C++ 2023 code that defines replaceable_if_eligible ortrivially_relocatable_if_eligible as macros is invalid
in this revision of C++[.](#library-2.sentence-4)

### [C.1.7](#mem) [[mem]](mem "20 Memory management library"): memory management library [[diff.cpp23.mem]](diff.cpp23.mem)

[1](#mem-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L278)

**Affected subclause:** [[c.malloc]](c.malloc)  


**Change:** Calling realloc with a non-null pointer and zero size
has erroneous behavior[.](#mem-1.sentence-1)

  


**Rationale:** The C standard library does not define this behavior[.](#mem-1.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code that calls realloc with a non-null pointer and a size of zero is erroneous and may change behavior[.](#mem-1.sentence-3)

### [C.1.8](#containers) [[containers]](containers "23 Containers library"): containers library [[diff.cpp23.containers]](diff.cpp23.containers)

[1](#containers-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L290)

**Affected subclause:** [[span.overview]](span.overview)  


**Change:** span<const T> is constructible from initializer_list<T>[.](#containers-1.sentence-1)

  


**Rationale:** Permit passing a braced initializer list to a function taking span[.](#containers-1.sentence-2)

  


**Effect on original feature:** Valid C++ 2023 code that relies on the lack of this constructor
may refuse to compile, or change behavior in this revision of C++[.](#containers-1.sentence-3)

[*Example [1](#containers-example-1)*: void one(pair<int, int>); // #1void one(span<const int>); // #2void t1() { one({1, 2}); } // ambiguous between #1 and #2; previously called #1void two(span<const int, 2>);void t2() { two({{1, 2}}); } // ill-formed; previously well-formedvoid *a[10];int x = span<void* const>{a, 0}.size(); // x is 2; previously 0 any b[10];int y = span<const any>{b, b + 10}.size(); // y is 2; previously 10 â *end example*]

### [C.1.9](#strings) [[strings]](strings "27 Strings library"): strings library [[diff.cpp23.strings]](diff.cpp23.strings)

[1](#strings-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L316)

**Affected subclause:** [[string.conversions]](string.conversions)  


**Change:** Output of floating-point overloads of to_string and to_wstring[.](#strings-1.sentence-1)

  


**Rationale:** Prevent loss of information and improve consistency with other formatting
facilities[.](#strings-1.sentence-2)

  


**Effect on original feature:** to_string and to_wstring function calls that take
floating-point arguments may produce a different output[.](#strings-1.sentence-3)

[*Example [1](#strings-example-1)*: auto s = std::to_string(1e-7); // "1e-07"// previously "0.000000" with '.' possibly// changed according to the global C locale â *end example*]

### [C.1.10](#io) [[input.output]](input.output "31 Input/output library"): input/output library [[diff.cpp23.io]](diff.cpp23.io)

[1](#io-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L335)

**Affected subclause:** [[istream.unformatted]](istream.unformatted)  


**Change:** Overloaded std​::​basic_istream<char, traits>​::​ignore[.](#io-1.sentence-1)

  


**Rationale:** Allow char values to be used as delimiters[.](#io-1.sentence-2)

  


**Effect on original feature:** Calls to istream​::​ignore with a second argument of char type
can change behavior[.](#io-1.sentence-3)

Calls to istream​::​ignore with a second argument that is neitherint nor char type can become ill-formed[.](#io-1.sentence-4)

[*Example [1](#io-example-1)*: std::istringstream in("\xF0\x9F\xA4\xA1 Clown Face");
in.ignore(100, '\xA1'); // ignore up to '\xA1' delimiter,// previously might have ignored to EOF in.ignore(100, -1L); // ambiguous overload,// previously equivalent to (int)-1L â *end example*]

### [C.1.11](#depr) [[depr]](depr "Annex D (normative) Compatibility features"): compatibility features [[diff.cpp23.depr]](diff.cpp23.depr)

[1](#depr-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L358)

**Change:** Remove the type alias allocator<T>​::​is_always_equal[.](#depr-1.sentence-1)

  


**Rationale:** Non-empty allocator classes derived from allocator needed to explicitly
define an is_always_equal member type so that allocator_traits would not use the one from the allocator base class[.](#depr-1.sentence-2)

  


**Effect on original feature:** It is simpler to correctly define an allocator class with an allocator base
class[.](#depr-1.sentence-3)

[*Example [1](#depr-example-1)*: template <class T>struct MyAlloc : allocator<T> {int tag;};

static_assert(!allocator_traits<MyAlloc<int>>::is_always_equal); // Error in C++ 2023,// OK in C++ 2026 â *end example*]

[2](#depr-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L380)

**Change:** Removal of atomic access API for shared_ptr objects[.](#depr-2.sentence-1)

  


**Rationale:** The old behavior was brittle[.](#depr-2.sentence-2)

shared_ptr objects using the old API were
not protected by the type system, and certain interactions with code not using
this API would, in some cases, silently produce undefined behavior[.](#depr-2.sentence-3)

A complete
type-safe replacement is provided in the form of atomic<shared_ptr<T>>[.](#depr-2.sentence-4)

  


**Effect on original feature:** A valid C++ 2023 program that relies on the presence of the removed functions
may fail to compile[.](#depr-2.sentence-5)

[3](#depr-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L392)

**Change:** Remove the basic_string​::​reserve() overload with no parameters[.](#depr-3.sentence-1)

  


**Rationale:** The overload of reserve with no parameters is redundant[.](#depr-3.sentence-2)

The shrink_to_fit member function can be used instead[.](#depr-3.sentence-3)

  


**Effect on original feature:** A valid C++ 2023 program that calls reserve() on a basic_string object may fail to compile[.](#depr-3.sentence-4)

The old functionality can be achieved by calling shrink_to_fit() instead,
or the function call can be safely eliminated with no side effects[.](#depr-3.sentence-5)

[4](#depr-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L404)

**Change:** Remove header <codecvt> and all its contents[.](#depr-4.sentence-1)

  


**Rationale:** The header has been deprecated for the previous three editions of this document
and no longer implements the current Unicode standard, supporting only the
obsolete UCS-2 encoding[.](#depr-4.sentence-2)

Ongoing support is at implementer's discretion,
exercising freedoms granted by [[zombie.names]](zombie.names "16.4.5.3.2 Zombie names")[.](#depr-4.sentence-3)

  


**Effect on original feature:** A valid C++ 2023 program #include-ing the header or importing the
header unit may fail to compile[.](#depr-4.sentence-4)

Code that uses any of the following names by
importing the standard library modules may fail to compile:

- [(4.1)](#depr-4.1)

codecvt_mode,

- [(4.2)](#depr-4.2)

codecvt_utf16,

- [(4.3)](#depr-4.3)

codecvt_utf8,

- [(4.4)](#depr-4.4)

codecvt_utf8_utf16,

- [(4.5)](#depr-4.5)

consume_header,

- [(4.6)](#depr-4.6)

generate_header, and

- [(4.7)](#depr-4.7)

little_endian[.](#depr-4.sentence-5)

[5](#depr-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L427)

**Change:** Remove header <strstream> and all its contents[.](#depr-5.sentence-1)

  


**Rationale:** The header has been deprecated since the original C++ standard; the[<spanstream>](span.streams.overview#header:%3cspanstream%3e "31.9.1 Overview [span.streams.overview]") header provides an updated, safer facility[.](#depr-5.sentence-2)

Ongoing support is at implementer's discretion,
exercising freedoms granted by [[zombie.names]](zombie.names "16.4.5.3.2 Zombie names")[.](#depr-5.sentence-3)

  


**Effect on original feature:** A valid C++ 2023 program #include-ing the header or importing the
header unit may become ill-formed[.](#depr-5.sentence-4)

Code that uses any of the following classes
by importing one of the standard library modules may become ill-formed:

- [(5.1)](#depr-5.1)

istrstream

- [(5.2)](#depr-5.2)

ostrstream

- [(5.3)](#depr-5.3)

strstream

- [(5.4)](#depr-5.4)

strstreambuf

[6](#depr-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L446)

**Change:** Remove convenience interfaces wstring_convert andwbuffer_convert[.](#depr-6.sentence-1)

  


**Rationale:** These features were underspecified with no clear error reporting mechanism and
were deprecated for the last three editions of this document[.](#depr-6.sentence-2)

Ongoing support is at implementer's discretion,
exercising freedoms granted by [[zombie.names]](zombie.names "16.4.5.3.2 Zombie names")[.](#depr-6.sentence-3)

  


**Effect on original feature:** A valid C++ 2023 program using these interfaces may become ill-formed[.](#depr-6.sentence-4)
