Annex C (informative) Compatibility [diff]

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

C.1.1 General [diff.cpp23.general]

Subclause [diff.cpp23] lists the differences between C++ and ISO C++ 2023, by the chapters of this document.

C.1.2 [expr]: expressions [diff.cpp23.expr]

Affected subclause: [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.

Rationale: Reinforcing type safety.

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.
[Example 1: enum E1 { e }; enum E2 { f }; bool b = e <= 3.7; // ill-formed; previously well-formed int k = f - e; // ill-formed; previously well-formed auto x = true ? e : f; // ill-formed; previously well-formed — end example]
Affected subclause: [expr.delete]
Change: Calling delete on a pointer to an incomplete class is ill-formed.

Rationale: Reduce undefined behavior.

Effect on original feature: A valid C++ 2023 program that calls delete on an incomplete class type is ill-formed.
[Example 2: struct S; void f(S *p) { delete p; // ill-formed; previously well-formed } struct S {}; — end example]

C.1.3 [dcl.dcl]: declarations [diff.cpp23.dcl.dcl]

Affected subclause: [dcl.init.list]
Change: Pointer comparisons between initializer_list objects' backing arrays are unspecified.

Rationale: Permit the implementation to store backing arrays in static read-only memory.

Effect on original feature: Valid C++ 2023 code that relies on the result of pointer comparison between backing arrays may change behavior.
[Example 1: 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]
Affected subclause: [dcl.array]
Change: Previously, T...[n] would declare a pack of function parameters.
T...[n] is now a pack-index-specifier.

Rationale: Improve the handling of packs.

Effect on original feature: Valid C++ 2023 code that declares a pack of parameters without specifying a declarator-id becomes ill-formed.
[Example 2: 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]

C.1.4 [temp]: templates [diff.cpp23.temp]

Affected subclause: [temp.constr]
Change: Some atomic constraints become fold expanded constraints.

Rationale: Permit the subsumption of fold expressions.

Effect on original feature: Valid C++ 2023 code may become ill-formed.
[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]

C.1.5 [library]: library introduction [diff.cpp23.library]

Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new: <debugging>, <hazard_pointer>, <inplace_vector>, <linalg>, <rcu>, and <text_encoding>.
Valid C++ 2023 code that #includes headers with these names may be invalid in this revision of C++.

C.1.6 [strings]: strings library [diff.cpp23.strings]

Affected subclause: [string.conversions]
Change: Output of floating-point overloads of to_string and to_wstring.

Rationale: Prevent loss of information and improve consistency with other formatting facilities.

Effect on original feature: to_string and to_wstring function calls that take floating-point arguments may produce a different output.
[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.7 [containers]: containers library [diff.cpp23.containers]

Affected subclause: [span.overview]
Change: span<const T> is constructible from initializer_list<T>.

Rationale: Permit passing a braced initializer list to a function taking span.

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++.
[Example 1: void one(pair<int, int>); // #1 void one(span<const int>); // #2 void t1() { one({1, 2}); } // ambiguous between #1 and #2; previously called #1 void two(span<const int, 2>); void t2() { two({{1, 2}}); } // ill-formed; previously well-formed void *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.8 [depr]: compatibility features [diff.cpp23.depr]

Change: Remove the type alias allocator<T>​::​is_always_equal.

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.

Effect on original feature: It is simpler to correctly define an allocator class with an allocator base class.
[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]
Change: Removal of atomic access API for shared_ptr objects.

Rationale: The old behavior was brittle.
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.
A complete type-safe replacement is provided in the form of atomic<shared_ptr<T>>.

Effect on original feature: A valid C++ 2023 program that relies on the presence of the removed functions may fail to compile.
Change: Remove the basic_string​::​reserve() overload with no parameters.

Rationale: The overload of reserve with no parameters is redundant.
The shrink_to_fit member function can be used instead.

Effect on original feature: A valid C++ 2023 program that calls reserve() on a basic_string object may fail to compile.
The old functionality can be achieved by calling shrink_to_fit() instead, or the function call can be safely eliminated with no side effects.
Change: Remove header <codecvt> and all its contents.

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.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program #include-ing the header or importing the header unit may fail to compile.
Code that uses any of the following names by importing the standard library modules may fail to compile:
Change: Remove header <strstream> and all its contents.

Rationale: The header has been deprecated since the original C++ standard; the <spanstream> header provides an updated, safer facility.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program #include-ing the header or importing the header unit may become ill-formed.
Code that uses any of the following classes by importing one of the standard library modules may become ill-formed:
Change: Remove convenience interfaces wstring_convert and wbuffer_convert.

Rationale: These features were underspecified with no clear error reporting mechanism and were deprecated for the last three editions of this document.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program using these interfaces may become ill-formed.