diff --git a/source/compatibility.tex b/source/compatibility.tex index 0bdb90b9cc..fd56f1a4d6 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1,6 +1,36 @@ %!TEX root = std.tex \infannex{diff}{Compatibility} +\rSec1[diff.cpp23]{\Cpp{} and ISO \CppXXIII{}} + +\rSec2[diff.cpp23.general]{General} + +\pnum +\indextext{summary!compatibility with ISO \CppXXIII{}}% +Subclause \ref{diff.cpp23} lists the differences between \Cpp{} and +ISO \CppXXIII{} (ISO/IEC 14882:2023, \doccite{Programming Languages --- \Cpp{}}), +by the chapters of this document. + +\rSec2[diff.cpp23.expr]{\ref{expr}: expressions} + +\diffref{dcl.init.list} +\change +Pointer comparisons between \tcode{initializer_list} objects' backing arrays +are unspecified. +\rationale +Permit the implementation to store backing arrays in static read-only memory. +\effect +Valid \CppXXIII{} code +that relies on the result of pointer comparison between backing arrays +may change behavior. +For example: +\begin{example} +bool ne(std::initializer_list a, std::initializer_list b) { + return a.begin() != b.begin() + 1; +} +bool b = ne({2,3}, {1,2,3}); // unspecified result; previously \tcode{false} +\end{example} + \rSec1[diff.cpp20]{\Cpp{} and ISO \CppXX{}} \rSec2[diff.cpp20.general]{General} diff --git a/source/declarations.tex b/source/declarations.tex index 124905b8f6..8725c426b0 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -5991,36 +5991,64 @@ an initializer list as if the implementation generated and materialized\iref{conv.rval} a prvalue of type ``array of $N$ \tcode{const E}'', -where $N$ is the number of elements in the -initializer list. Each element of that array is copy-initialized with the +where $N$ is the number of elements in the initializer list; +this is called the initializer list's \defnadj{backing}{array}. +Each element of the backing array is copy-initialized with the corresponding element of the initializer list, and the \tcode{std::initializer_list} object is constructed to refer to that array. \begin{note} A constructor or conversion function selected for the copy is required to be accessible\iref{class.access} in the context of the initializer list. \end{note} -If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. +If a narrowing conversion is required to initialize any of the elements, +the program is ill-formed. +Whether all backing arrays are distinct +(that is, are stored in non-overlapping objects) is unspecified. + +\pnum +The backing array has the same lifetime as any other temporary +object\iref{class.temporary}, except that initializing an +\tcode{initializer_list} object from the array extends the lifetime of +the array exactly like binding a reference to a temporary. \begin{example} \begin{codeblock} -struct X { - X(std::initializer_list v); +void f(std::initializer_list il); +void g(float x) { + f({1, x, 3}); +} +void h() { + f({1, 2, 3}); +} + +struct A { + mutable int i; }; -X x{ 1,2,3 }; +void q(std::initializer_list); +void r() { + q({A{1}, A{2}, A{3}}); +} \end{codeblock} The initialization will be implemented in a way roughly equivalent to this: \begin{codeblock} -const double __a[3] = {double{1}, double{2}, double{3}}; -X x(std::initializer_list(__a, __a+3)); +void g(float x) { + const double __a[3] = {double{1}, double{x}, double{3}}; // backing array + f(std::initializer_list(__a, __a+3)); +} +void h() { + static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array + f(std::initializer_list(__b, __b+3)); +} +void r() { + const A __c[3] = {A{1}, A{2}, A{3}}; // backing array + q(std::initializer_list(__c, __c+3)); +} \end{codeblock} -assuming that the implementation can construct an \tcode{initializer_list} object with a pair of pointers. +assuming that the implementation +can construct an \tcode{initializer_list} object with a pair of pointers, and +with the understanding that \tcode{__b} does not outlive the call to \tcode{f}. \end{example} -\pnum -The array has the same lifetime as any other temporary -object\iref{class.temporary}, except that initializing an -\tcode{initiali\-zer_list} object from the array extends the lifetime of -the array exactly like binding a reference to a temporary. \begin{example} \begin{codeblock} typedef std::complex cmplx; @@ -6047,9 +6075,6 @@ a temporary array to a reference member, so the program is ill-formed\iref{class.base.init}. \end{example} -\begin{note} -The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer can be so allocated. -\end{note} \pnum A \defnadj{narrowing}{conversion} is an implicit conversion diff --git a/source/macros.tex b/source/macros.tex index 13a4203294..3d6541e5aa 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -274,6 +274,7 @@ \newcommand{\CppXIV}{\Cpp{} 2014} \newcommand{\CppXVII}{\Cpp{} 2017} \newcommand{\CppXX}{\Cpp{} 2020} +\newcommand{\CppXXIII}{\Cpp{} 2023} \newcommand{\opt}[1]{#1\ensuremath{_\mathit{\color{black}opt}}} \newcommand{\bigoh}[1]{\ensuremath{\mathscr{O}(#1)}}