diff --git a/source/declarations.tex b/source/declarations.tex index b0df1c3673..2a5b1caaa3 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -5683,10 +5683,14 @@ \end{codeblock} \end{example} -\item Otherwise, if \tcode{T} is a reference type, a prvalue of the type -referenced by \tcode{T} is generated. +\item Otherwise, if \tcode{T} is a reference type, a prvalue is generated. The prvalue initializes its result object by copy-list-initialization. The prvalue is then used to direct-initialize the reference. +The type of the temporary is the type referenced by \tcode{T}, +unless \tcode{T} is ``reference to array of unknown bound of \tcode{U}'', +in which case the type of the temporary is +the type of \tcode{x} in the declaration \tcode{U x[] $H$}, +where $H$ is the initializer list. \begin{note} As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. \end{note} diff --git a/source/expressions.tex b/source/expressions.tex index 2e3ef62dea..c262d3e483 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -324,25 +324,6 @@ \tcode{T} is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to \tcode{T} prior to any further analysis. -\pnum -The \defnadj{cv-combined}{type} of two types \tcode{T1} and \tcode{T2} -is a type \tcode{T3} -similar to \tcode{T1} whose cv-qualification signature\iref{conv.qual} is: -\begin{itemize} -\item -for every $i > 0$, $\cv{}^3_i$ is the union of -$\cv{}^1_i$ and $\cv{}^2_i$; - -\item -if the resulting $\cv{}^3_i$ is different from -$\cv{}^1_i$ or $\cv{}^2_i$, then -\tcode{const} is added to every $\cv{}^3_k$ for $0 < k < i$. -\end{itemize} - -\begin{note} Given similar types \tcode{T1} and \tcode{T2}, this -construction ensures that -both can be converted to \tcode{T3}. \end{note} - \pnum \indextext{pointer!composite pointer type}% The \defn{composite pointer type} of @@ -748,34 +729,34 @@ \indextext{type!similar|see{similar types}}% Two types $\tcode{T}_1$ and $\tcode{T}_2$ are \defnx{similar}{similar types} if they have cv-decompositions with the same $n$ -such that corresponding $P_i$ components are the same +such that corresponding $P_i$ components are either the same +or one is ``array of $N_i$'' and the other is ``array of unknown bound of'', and the types denoted by \tcode{U} are the same. \pnum -A prvalue of type $\tcode{T}_1$ -can be converted to type $\tcode{T}_2$ -if the following conditions are satisfied, -% NB: forbid line break between 'where' and 'cv' -% to stop superscript j from running into -% descender of p on the previous line. -where~$\cv{}_i^j$ denotes the cv-qualifiers in the cv-qualification signature of $\tcode{T}_j$:% -\footnote{These rules ensure that const-safety is preserved by the conversion.} - +The \defnadj{cv-combined}{type} of two types \tcode{T1} and \tcode{T2} +is the type \tcode{T3} +similar to \tcode{T1} whose cv-decomposition is such that: \begin{itemize} -\item $\tcode{T}_1$ and $\tcode{T}_2$ are similar. - -\item For every $i > 0$, if \tcode{const} is in $\cv{}_i^1$ then \tcode{const} is in $\cv{}_i^2$, and similarly for \tcode{volatile}. - -\item If the $\cv{}_i^1$ and $\cv{}_i^2$ are different, -then \tcode{const} is in every $\cv{}_k^2$ for $0 < k < i$. +\item +for every $i > 0$, $\cv{}^3_i$ is the union of +$\cv{}^1_i$ and $\cv{}^2_i$; +\item +if either $P^1_i$ or $P^2_i$ is ``array of unknown bound of'', +$P^3_i$ is ``array of unknown bound of'', otherwise it is $P^1_i$; +\item +if the resulting $\cv{}^3_i$ is different from $\cv{}^1_i$ or $\cv{}^2_i$, +or the resulting $P^3_i$ is different from $P^1_i$ or $P^2_i$, +then \tcode{const} is added to every $\cv{}^3_k$ for $0 < k < i$. \end{itemize} - +A prvalue of type $\tcode{T}_1$ +can be converted to type $\tcode{T}_2$ +if the cv-combined type of $\tcode{T}_1$ and $\tcode{T}_2$ is $\tcode{T}_2$. \begin{note} If a program could assign a pointer of type \tcode{T**} to a pointer of type \tcode{const} \tcode{T**} (that is, if line \#1 below were allowed), a program could inadvertently modify a const object (as it is done on line \#2). For example, - \begin{codeblock} int main() { const char c = 'c'; @@ -786,6 +767,11 @@ } \end{codeblock} \end{note} +\begin{note} +Given similar types \tcode{T1} and \tcode{T2}, this +construction ensures that +both can be converted to the cv-combined type of \tcode{T1} and \tcode{T2}. +\end{note} \pnum \begin{note} @@ -3997,8 +3983,10 @@ \pnum For two similar types \tcode{T1} and \tcode{T2}\iref{conv.qual}, a prvalue of type \tcode{T1} may be explicitly -converted to the type \tcode{T2} using a \tcode{const_cast}. The result -of a \tcode{const_cast} refers to the original entity. +converted to the type \tcode{T2} using a \tcode{const_cast} +if, considering the cv-decompositions of both types, +each $P^1_i$ is the same as $P^2_i$ for all $i$. +The result of a \tcode{const_cast} refers to the original entity. \begin{example} \begin{codeblock} typedef int *A[3]; // array of 3 pointer to \tcode{int} diff --git a/source/overloading.tex b/source/overloading.tex index e25b2dea6d..9c536171a3 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -2490,10 +2490,13 @@ \end{example} \pnum -Otherwise, if the parameter type is ``array of \tcode{N} \tcode{X}'', -if there exists an implicit conversion sequence for each element of the array -from the corresponding element of the initializer list (or from \tcode{\{\}} -if there is no such element), the implicit conversion sequence is +Otherwise, if the parameter type is ``array of \tcode{N} \tcode{X}'' +or ``array of unknown bound of \tcode{X}'', +if there exists an implicit conversion sequence +from each element of the initializer list +(and from \tcode{\{\}} in the former case +if \tcode{N} exceeds the number of elements in the initializer list) +to \tcode{X}, the implicit conversion sequence is the worst such implicit conversion sequence. \pnum @@ -2662,19 +2665,35 @@ \tcode{L2} does not, or, if not that, \item -\tcode{L1} converts to type ``array of \tcode{N1} \tcode{T}'', \tcode{L2} converts to -type ``array of \tcode{N2} \tcode{T}'', and \tcode{N1} is smaller than \tcode{N2}, +\tcode{L1} and \tcode{L2} convert to arrays of the same element type, and +either the number of elements $n_1$ initialized by \tcode{L1} +is less than the number of elements $n_2$ initialized by \tcode{L2}, or +$n_1 = n_2$ and +\tcode{L2} converts to an array of unknown bound and \tcode{L1} does not, \end{itemize} even if one of the other rules in this paragraph would otherwise apply. \begin{example} \begin{codeblock} - void f1(int); // \#1 - void f1(std::initializer_list); // \#2 - void g1() { f1({42}); } // chooses \#2 +void f1(int); // \#1 +void f1(std::initializer_list); // \#2 +void g1() { f1({42}); } // chooses \#2 - void f2(std::pair); // \#3 - void f2(std::initializer_list); // \#4 - void g2() { f2({"foo","bar"}); } // chooses \#4 +void f2(std::pair); // \#3 +void f2(std::initializer_list); // \#4 +void g2() { f2({"foo","bar"}); } // chooses \#4 +\end{codeblock} +\end{example} +\begin{example} +\begin{codeblock} +void f(int (&&)[] ); // \#1 +void f(double (&&)[] ); // \#2 +void f(int (&&)[2]); // \#3 + +f( {1} ); // Calls \#1: Better than \#2 due to conversion, better than \#3 due to bounds +f( {1.0} ); // Calls \#2: Identity conversion is better than floating-integral conversion +f( {1.0, 2.0} ); // Calls \#2: Identity conversion is better than floating-integral conversion +f( {1, 2} ); // Calls \#3: Converting to array of known bound is better than to unknown bound, + // and an identity conversion is better than floating-integral conversion \end{codeblock} \end{example} @@ -2758,16 +2777,10 @@ or, if not that, \item -\tcode{S1} -and -\tcode{S2} -differ only in their qualification conversion and yield similar types -\tcode{T1} -and -\tcode{T2}\iref{conv.qual}, respectively, and the cv-qualification signature of type -\tcode{T1} -is a proper subset of the cv-qualification signature of type -\tcode{T2} +\tcode{S1} and \tcode{S2} differ only +in their qualification conversion\iref{conv.qual} and +yield similar types \tcode{T1} and \tcode{T2}, respectively, +where \tcode{T1} can be converted to \tcode{T2} by a qualification conversion \begin{example} \begin{codeblock} int f(const volatile int *);