%!TEX root = std.tex
\rSec0[expr]{Expressions}

\gramSec[gram.expr]{Expressions}

\indextext{\idxcode{operator new}|seealso{\tcode{new}}}%
\indextext{\idxcode{operator delete}|seealso{\tcode{delete}}}%
\indextext{usual arithmetic conversions|see{conversion, usual arithmetic}}%
\indextext{\idxcode{==}|see{operator, equality}}%
\indextext{\idxcode{"!=}|see{operator, inequality}}
\indextext{\idxcode{static_cast}|see{cast, static}}%
\indextext{\idxcode{dynamic_cast}|see{cast, dynamic}}%
\indextext{\idxcode{const_cast}|see{cast, const}}%
\indextext{\idxcode{reinterpret_cast}|see{cast, reinterpret}}

\rSec1[expr.pre]{Preamble}

\pnum
\indextext{expression|(}%
\begin{note}
\ref{expr} defines the syntax, order of evaluation, and meaning
of expressions.
\begin{footnote}
The precedence of operators is not directly specified, but it can be
derived from the syntax.
\end{footnote}
An expression is a sequence of operators and operands that specifies a
computation. An expression can result in a value and can cause side
effects.
\end{note}

\pnum
\indextext{operator!overloaded}%
\begin{note}
Operators can be overloaded, that is, given meaning when applied to
expressions of class type\iref{class} or enumeration
type\iref{dcl.enum}. Uses of overloaded operators are transformed into
function calls as described in~\ref{over.oper}. Overloaded operators
obey the rules for syntax and evaluation order specified in \ref{expr.compound},
but the requirements of operand type and value category are replaced
by the rules for function call. Relations between operators, such as
\tcode{++a} meaning \tcode{a += 1}, are not guaranteed for overloaded
operators\iref{over.oper}.
\end{note}

\pnum
Subclause \ref{expr.compound} defines the effects of operators when applied to types
for which they have not been overloaded. Operator overloading shall not
modify the rules for the \defnadj{built-in}{operators},
that is, for operators applied to types for which they are defined by this
Standard. However, these built-in operators participate in overload
resolution, and as part of that process user-defined conversions will be
considered where necessary to convert the operands to types appropriate
for the built-in operator. If a built-in operator is selected, such
conversions will be applied to the operands before the operation is
considered further according to the rules in \ref{expr.compound};
see~\ref{over.match.oper}, \ref{over.built}.

\pnum
\indextext{exception!arithmetic}%
\indextext{exception!undefined arithmetic}%
\indextext{overflow!undefined}%
\indextext{zero!division by undefined}%
\indextext{zero!remainder undefined}%
If during the evaluation of an expression, the result is not
mathematically defined or not in the range of representable values for
its type, the behavior is undefined.
\begin{note}
\indextext{overflow}%
Treatment of division by zero, forming a remainder using a zero divisor,
and all floating-point exceptions varies among machines, and is sometimes
adjustable by a library function.
\end{note}

\pnum
\indextext{operator!precedence of}%
\indextext{expression!order of evaluation of}%
\begin{note}
The implementation can regroup operators according to
the usual mathematical rules only
where the operators really are associative or commutative.
\begin{footnote}
Overloaded
operators are never assumed to be associative or commutative.
\end{footnote}
For example, in the following fragment
\begin{codeblock}
int a, b;
@\commentellip@
a = a + 32760 + b + 5;
\end{codeblock}
the expression statement behaves exactly the same as
\begin{codeblock}
a = (((a + 32760) + b) + 5);
\end{codeblock}
due to the associativity and precedence of these operators. Thus, the
result of the sum \tcode{(a + 32760)} is next added to \tcode{b}, and
that result is then added to \tcode{5} which results in the value assigned to
\tcode{a}. On a machine in which overflows produce an exception and in
which the range of values representable by an \tcode{int} is
\crange{-32768}{+32767}, the implementation cannot rewrite this
expression as
\begin{codeblock}
a = ((a + b) + 32765);
\end{codeblock}
since if the values for \tcode{a} and \tcode{b} were, respectively,
$-32754$ and $-15$, the sum \tcode{a + b} would produce an exception while
the original expression would not; nor can the expression be rewritten
as either
\begin{codeblock}
a = ((a + 32765) + b);
\end{codeblock}
or
\begin{codeblock}
a = (a + (b + 32765));
\end{codeblock}
since the values for \tcode{a} and \tcode{b} might have been,
respectively, 4 and $-8$ or $-17$ and 12. However on a machine in which
overflows do not produce an exception and in which the results of
overflows are reversible, the above expression statement can be
rewritten by the implementation in any of the above ways because the
same result will occur.
\end{note}

\pnum
The values of the floating-point operands and
the results of floating-point expressions
may be represented in greater precision and range than that
required by the type; the types are not changed\
thereby.
\begin{footnote}
The cast and assignment operators must still perform their specific
conversions as described in~\ref{expr.type.conv}, \ref{expr.cast},
\ref{expr.static.cast} and~\ref{expr.assign}.
\end{footnote}

\rSec1[expr.prop]{Properties of expressions}

\rSec2[basic.lval]{Value category}
\pnum
Expressions are categorized according to the taxonomy in \fref{basic.lval}.

\begin{importgraphic}
{Expression category taxonomy}
{basic.lval}
{valuecategories.pdf}
\end{importgraphic}

\begin{itemize}
\item A \defn{glvalue} is an expression
whose evaluation determines the identity of
an object, function, non-static data member, or
a direct base class relationship.
\item A \defn{prvalue} is an expression whose evaluation initializes an object
or computes the value of an operand of an operator,
as specified by the context in which it appears,
or an expression that has type \cv{}~\keyword{void}.
\item An \defn{xvalue} is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).
\item An \defn{lvalue} is a glvalue that is not an xvalue.
\item An \defn{rvalue} is a prvalue or an xvalue.
\end{itemize}

\pnum
Every expression belongs to exactly one of the fundamental categories in this
taxonomy: lvalue, xvalue, or prvalue. This property of an expression is called
its \defn{value category}.
\begin{note}
The discussion of each built-in operator in
\ref{expr.compound} indicates the category of the value it yields and the value categories
of the operands it expects. For example, the built-in assignment operators expect that
the left operand is an lvalue and that the right operand is a prvalue and yield an
lvalue as the result. User-defined operators are functions, and the categories of
values they expect and yield are determined by their parameter and return types.
\end{note}

\pnum
\begin{note}
Historically, lvalues and rvalues were so-called
because they could appear on the left- and right-hand side of an assignment
(although this is no longer generally true);
glvalues are ``generalized'' lvalues,
prvalues are ``pure'' rvalues,
and xvalues are ``eXpiring'' lvalues.
Despite their names, these terms apply to expressions, not values.
\end{note}

\pnum
\indextext{expression!rvalue reference}%
\begin{note}
An expression is an xvalue if it is:
\begin{itemize}
\item a move-eligible \grammarterm{id-expression}\iref{expr.prim.id.unqual}
or \grammarterm{splice-expression}\iref{expr.prim.splice},

\item the result of calling a function, whether implicitly or explicitly,
whose return type is an rvalue reference to object type\iref{expr.call},

\item a cast to an rvalue reference to
object type\iref{expr.type.conv,expr.dynamic.cast,expr.static.cast,
expr.reinterpret.cast,expr.const.cast,expr.cast},

\item a subscripting operation with an xvalue array operand\iref{expr.sub},

\item a class member access expression designating a non-static data member
of non-reference type
in which the object expression is an xvalue\iref{expr.ref}, or

\item a \tcode{.*} pointer-to-member expression in which the first operand is
an xvalue and the second operand is a pointer to data member\iref{expr.mptr.oper}.
\end{itemize}
In general, the effect of this rule is that named rvalue references are
treated as lvalues and unnamed rvalue references to objects are treated as
xvalues; rvalue references to functions are treated as lvalues whether named or not.
\end{note}

\begin{example}
\begin{codeblock}
struct A {
  int m;
};
A&& operator+(A, A);
A&& f();

A a;
A&& ar = static_cast<A&&>(a);
\end{codeblock}

The expressions \tcode{f()}, \tcode{f().m}, \tcode{\keyword{static_cast}<A\&\&>(a)}, and \tcode{a + a}
are xvalues. The expression \tcode{ar} is an lvalue.
\end{example}

\pnum
The \defnx{result}{result!glvalue} of a glvalue is the entity denoted by the expression.
The \defnx{result}{result!prvalue} of a prvalue
is the value that the expression stores into its context;
a prvalue that has type \cv{}~\keyword{void} has no result.
A prvalue whose result is the value \placeholder{V}
is sometimes said to have or name the value \placeholder{V}.
The \defn{result object} of a prvalue is the object initialized by the prvalue;
a prvalue that has type \cv{}~\keyword{void}
has no result object.
\begin{note}
Except when the prvalue is the operand of a \grammarterm{decltype-specifier},
a prvalue of object type always has a result object.
For a discarded prvalue that has type other than \cv{}~\keyword{void},
a temporary object is materialized; see \ref{expr.context}.
\end{note}

\pnum
Whenever a glvalue appears as an operand of an operator that
requires a prvalue for that operand, the
lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array},
or function-to-pointer\iref{conv.func} standard conversions are
applied to convert the expression to a prvalue.
\begin{note}
An attempt to bind an rvalue reference to an lvalue is not such a context; see~\ref{dcl.init.ref}.
\end{note}
\begin{note}
Because cv-qualifiers are removed from the type of an expression of
non-class type when the expression is converted to a prvalue, an lvalue
of type \tcode{\keyword{const} \keyword{int}} can, for example, be used where
a prvalue of type \keyword{int} is required.
\end{note}
\begin{note}
There are no prvalue bit-fields; if a bit-field is converted to a
prvalue\iref{conv.lval}, a prvalue of the type of the bit-field is
created, which might then be promoted\iref{conv.prom}.
\end{note}

\pnum
Unless otherwise specified\iref{expr.reinterpret.cast, expr.const.cast},
whenever a prvalue
that is not the result of the lvalue-to-rvalue conversion\iref{conv.lval}
appears as an operand of an operator,
the temporary materialization conversion\iref{conv.rval} is
applied to convert the expression to an xvalue.

\pnum
\begin{note}
The discussion of reference initialization in~\ref{dcl.init.ref} and of
temporaries in~\ref{class.temporary} indicates the behavior of lvalues
and rvalues in other significant contexts.
\end{note}

\pnum
Unless otherwise indicated\iref{dcl.type.decltype},
a prvalue shall always have complete type or the \keyword{void} type;
if it has a class type or (possibly multidimensional) array of class type,
that class shall not be an abstract class\iref{class.abstract}.
A glvalue shall not have type \cv{}~\keyword{void}.
\begin{note}
A glvalue can have complete or incomplete non-\keyword{void} type.
Class and array prvalues can have cv-qualified types; other prvalues
always have cv-unqualified types. See \ref{expr.type}.
\end{note}

\pnum
An lvalue is \defn{modifiable} unless its type is const-qualified
or is a function type.
\begin{note}
A program that attempts
to modify an object through a nonmodifiable lvalue or through an rvalue
is ill-formed\iref{expr.assign,expr.post.incr,expr.pre.incr}.
\end{note}

\pnum
An object of dynamic type $\tcode{T}_\text{obj}$ is
\defn{type-accessible} through a glvalue of type $\tcode{T}_\text{ref}$
if $\tcode{T}_\text{ref}$ is similar\iref{conv.qual} to:
\begin{itemize}
\item $\tcode{T}_\text{obj}$,

\item a type that is the signed or unsigned type corresponding to $\tcode{T}_\text{obj}$, or

\item a \keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, or \tcode{std::byte} type.
\end{itemize}
If a program attempts to access\iref{defns.access}
the stored value of an object through a glvalue
through which it is not type-accessible,
the behavior is undefined.
\begin{footnote}
The intent of this list is to specify those circumstances in which an
object can or cannot be aliased.
\end{footnote}
If a program invokes
a defaulted copy/move constructor or copy/move assignment operator
for a union of type \tcode{U} with a glvalue argument
that does not denote an object of type \cv{}~\tcode{U} within its lifetime,
the behavior is undefined.
\begin{note}
In C, an entire object of structure type can be accessed, e.g., using assignment.
By contrast, \Cpp{} has no notion of accessing an object of class type
through an lvalue of class type.
\end{note}

\rSec2[expr.type]{Type}

\pnum
\indextext{expression!reference}%
If an expression initially has the type ``reference to
\tcode{T}''\iref{dcl.ref,dcl.init.ref}, the type is adjusted to
\tcode{T} prior to any further analysis;
the value category of the expression is not altered.
Let $X$ be the object or function denoted by the reference.
If a pointer to $X$ would be valid in
the context of the evaluation of the expression\iref{basic.fundamental},
the result designates $X$;
otherwise, the behavior is undefined.
\begin{note}
Before the lifetime of the reference has started or after it has ended,
the behavior is undefined (see~\ref{basic.life}).
\end{note}

\pnum
If a prvalue initially has the type ``\cv{}~\tcode{T}'', where
\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
\indextext{pointer!composite pointer type}%
The \defn{composite pointer type} of
two operands \tcode{p1} and
\tcode{p2} having types \tcode{T1} and \tcode{T2}, respectively, where at least one is a
pointer or pointer-to-member type or
\tcode{std::nullptr_t}, is:
\begin{itemize}
\item
if both \tcode{p1} and \tcode{p2} are null pointer constants,
\tcode{std::nullptr_t};

\item
if either \tcode{p1} or \tcode{p2} is a null pointer constant, \tcode{T2} or \tcode{T1},
respectively;

\item
if \tcode{T1} or \tcode{T2} is ``pointer to \cvqual{cv1} \keyword{void}'' and the
other type is ``pointer to \cvqual{cv2} \tcode{T}'',
where \tcode{T} is an object type or \keyword{void},
``pointer to \cvqual{cv12} \keyword{void}'',
where \cvqual{cv12} is the union of \cvqual{cv1} and \cvqual{cv2};

\item
if \tcode{T1} or \tcode{T2} is ``pointer to \keyword{noexcept} function'' and the
other type is ``pointer to function'', where the function types are otherwise the same,
``pointer to function'';

\item
if \tcode{T1} is ``pointer to \tcode{C1}'' and \tcode{T2} is ``pointer to
\tcode{C2}'', where \tcode{C1} is reference-related to \tcode{C2} or \tcode{C2} is
reference-related to \tcode{C1}\iref{dcl.init.ref},
the qualification-combined type\iref{conv.qual}
of \tcode{T1} and \tcode{T2} or the qualification-combined type of \tcode{T2} and \tcode{T1},
respectively;

\item
if \tcode{T1} or \tcode{T2} is
``pointer to member of \tcode{C1} of type function'',
the other type is
``pointer to member of \tcode{C2} of type \keyword{noexcept} function'', and
\tcode{C1} is reference-related to \tcode{C2} or
\tcode{C2} is reference-related to \tcode{C1}\iref{dcl.init.ref},
where the function types are otherwise the same,
``pointer to member of \tcode{C2} of type function'' or
``pointer to member of \tcode{C1} of type function'', respectively;

\item
if \tcode{T1} is
``pointer to member of \tcode{C1} of type \cvqual{cv1} \tcode{U}'' and
\tcode{T2} is
``pointer to member of \tcode{C2} of type \cvqual{cv2} \tcode{U}'',
for some non-function type \tcode{U},
where \tcode{C1} is
reference-related to \tcode{C2} or \tcode{C2} is reference-related to
\tcode{C1}\iref{dcl.init.ref}, the qualification-combined type of \tcode{T2} and \tcode{T1} or the qualification-combined type
of \tcode{T1} and \tcode{T2}, respectively;

\item
if \tcode{T1} and \tcode{T2} are similar types\iref{conv.qual}, the qualification-combined type of \tcode{T1} and
\tcode{T2};

\item
otherwise, a program that necessitates the determination of a
composite pointer type is ill-formed.
\end{itemize}

\begin{example}
\begin{codeblock}
typedef void *p;
typedef const int *q;
typedef int **pi;
typedef const int **pci;
\end{codeblock}

The composite pointer type of \tcode{p} and \tcode{q} is ``pointer to \tcode{\keyword{const} \keyword{void}}''; the
composite pointer type of \tcode{pi} and \tcode{pci} is ``pointer to \tcode{\keyword{const}} pointer to
\tcode{\keyword{const} \keyword{int}}''.
\end{example}

\rSec2[expr.context]{Context dependence}

\pnum
\label{term.unevaluated.operand}%
In some contexts, \defnx{unevaluated operands}{unevaluated operand}
appear\iref{expr.prim.req.simple,
expr.prim.req.compound,
expr.typeid,
expr.sizeof,
expr.unary.noexcept,
expr.reflect,
dcl.type.decltype,
temp.pre,
temp.concept}.
An unevaluated operand is not evaluated.
\begin{note}
In an unevaluated operand, a non-static class member can be
named\iref{expr.prim.id} and naming of objects or functions does not, by
itself, require that a definition be provided\iref{basic.def.odr}.
An unevaluated operand is considered a full-expression\iref{intro.execution}.
\end{note}

\pnum
In some contexts, an expression only appears for its side effects. Such an
expression is called a \defn{discarded-value expression}.
The array-to-pointer\iref{conv.array}
and function-to-pointer\iref{conv.func} standard conversions are not
applied. The lvalue-to-rvalue conversion\iref{conv.lval} is applied
if and only if
the expression is a glvalue of volatile-qualified type and it is one of the
following:

\begin{itemize}
\item \tcode{(} \grammarterm{expression} \tcode{)}, where
  \grammarterm{expression} is one of these expressions,
\item \grammarterm{id-expression}\iref{expr.prim.id},
\item \grammarterm{splice-expression}\iref{expr.prim.splice},
\item subscripting\iref{expr.sub},
\item class member access\iref{expr.ref},
\item indirection\iref{expr.unary.op},
\item pointer-to-member operation\iref{expr.mptr.oper},
\item conditional expression\iref{expr.cond} where both the second and the
      third operands are one of these expressions, or
\item comma expression\iref{expr.comma} where the right operand is one of
      these expressions.
\end{itemize}

\begin{note}
Using an overloaded operator causes a function call; the
above covers only operators with built-in meaning.
\end{note}
The temporary materialization conversion\iref{conv.rval} is applied
if the (possibly converted) expression is a prvalue of object type.
\begin{note}
If the original expression is an lvalue of class type,
it must have a volatile copy constructor to initialize the temporary object
that is the result object of the temporary materialization conversion.
\end{note}
The expression is evaluated and its result (if any) is discarded.

\rSec1[conv]{Standard conversions}

\rSec2[conv.general]{General}

\indextext{implicit conversion|see{conversion, implicit}}
\indextext{contextually converted to \tcode{bool}|see{conversion, contextual to \tcode{bool}}}
\indextext{rvalue!lvalue conversion to|see{conversion, lvalue-to-rvalue}}%

\pnum
\indextext{conversion!standard|(}%
\indextext{conversion!implicit}%
Standard conversions are implicit conversions with built-in meaning.
\ref{conv} enumerates the full set of such conversions. A
\defnx{standard conversion sequence}{conversion sequence!standard} is a sequence of standard
conversions in the following order:

\begin{itemize}
\item Zero or one conversion from the following set: lvalue-to-rvalue
conversion, array-to-pointer conversion, and function-to-pointer
conversion.

\item Zero or one conversion from the following set: integral
promotions, floating-point promotion, integral conversions, floating-point
conversions, floating-integral conversions, pointer conversions,
pointer-to-member conversions, and boolean conversions.

\item Zero or one function pointer conversion.

\item Zero or one qualification conversion.
\end{itemize}

\begin{note}
A standard conversion sequence can be empty, i.e., it can consist of no
conversions.
\end{note}
A standard conversion sequence will be applied to
an expression if necessary to convert it to an expression having
a required destination type and value category.

\pnum
\begin{note}
Expressions with a given type will be implicitly converted to other
types in several contexts:

\begin{itemize}
\item When used as operands of operators. The operator's requirements
for its operands dictate the destination type\iref{expr.compound}.

\item When used in the condition of an \keyword{if} statement\iref{stmt.if} or
iteration statement\iref{stmt.iter}. The destination type is
\keyword{bool}.

\item When used in the expression of a \keyword{switch} statement\iref{stmt.switch}.
The destination type is integral.

\item When used as the source expression for an initialization (which
includes use as an argument in a function call and use as the expression
in a \keyword{return} statement). The type of the entity being initialized
is (generally) the destination type.
See~\ref{dcl.init}, \ref{dcl.init.ref}.
\end{itemize}
\end{note}

\pnum
An expression $E$ can be
\defnx{implicitly converted}{conversion!implicit} to a type \tcode{T} if and only if the
declaration \tcode{T t = $E$;} is well-formed, for some invented temporary
variable \tcode{t}\iref{dcl.init}.

\pnum
Certain language constructs require that an expression be converted to a Boolean
value. An expression $E$ appearing in such a context is said to be
\defnx{contextually converted to \tcode{bool}}{conversion!contextual to \tcode{bool}} and is well-formed if and only if
the declaration \tcode{\keyword{bool} t($E$);} is well-formed, for some invented temporary
variable \tcode{t}\iref{dcl.init}.

\pnum
Certain language constructs require conversion to a value having
one of a specified set of types appropriate to the construct. An
expression $E$ of class type \tcode{C} appearing in such a
context is said to be
\indextext{conversion!contextual}%
\defn{contextually implicitly converted} to a specified type \tcode{T} and is
well-formed if and only if $E$ can be implicitly converted to a type \tcode{T}
that is determined as follows:
\tcode{C} is searched for non-explicit conversion functions
whose return type is \cv{} \tcode{T} or reference to \cv{}
\tcode{T} such that \tcode{T} is allowed by the context.
There shall be exactly one such \tcode{T}.

\pnum
The effect of any implicit
conversion is the same as performing the corresponding declaration and initialization
and then using the temporary variable as the result of the conversion.
The result is an lvalue if \tcode{T} is an lvalue reference
type or an rvalue reference to function type\iref{dcl.ref},
an xvalue if \tcode{T} is an rvalue reference to object type,
and a prvalue otherwise. The expression $E$
is used as a glvalue if and only if the initialization uses it as a glvalue.

\pnum
\begin{note}
For class types, user-defined conversions are considered as well;
see~\ref{class.conv}. In general, an implicit conversion
sequence\iref{over.best.ics} consists of a standard conversion
sequence followed by a user-defined conversion followed by another
standard conversion sequence.
\end{note}

\pnum
\begin{note}
There are some contexts where certain conversions are suppressed. For
example, the lvalue-to-rvalue conversion is not done on the operand of
the unary \tcode{\&} operator. Specific exceptions are given in the
descriptions of those operators and contexts.
\end{note}

\rSec2[conv.lval]{Lvalue-to-rvalue conversion}

\pnum
\indextext{conversion!lvalue-to-rvalue}%
\indextext{type!incomplete}%
A glvalue\iref{basic.lval} of a non-function, non-array type \tcode{T}
can be converted to
a prvalue.
\begin{footnote}
For historical reasons, this conversion is called the ``lvalue-to-rvalue''
conversion, even though that name does not accurately reflect the taxonomy
of expressions described in~\ref{basic.lval}.
\end{footnote}
If \tcode{T} is an incomplete type, a
program that necessitates this conversion is ill-formed. If \tcode{T}
is a non-class type, the type of the prvalue is
the cv-unqualified version of \tcode{T}. Otherwise, the type of the
prvalue is \tcode{T}.
\begin{footnote}
In \Cpp{} class and array prvalues can have cv-qualified types.
This differs from C, in which non-lvalues never have
cv-qualified types.
\end{footnote}

\pnum
When an lvalue-to-rvalue conversion
is applied to an expression $E$, and either
\begin{itemize}
\item $E$ is not potentially evaluated, or
\item the evaluation of $E$ results in the evaluation of a member
      $E_\tcode{x}$ of the set of potential results of $E$, and $E_\tcode{x}$
      names a variable \tcode{x} that is not odr-used by
      $E_\tcode{x}$\iref{basic.def.odr},
\end{itemize}
the value contained in the referenced object is not accessed.
\begin{example}
\begin{codeblock}
struct S { int n; };
auto f() {
  S x { 1 };
  constexpr S y { 2 };
  return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false);   // undefined behavior: access of \tcode{x.n} outside its lifetime
int n = g(true);    // OK, does not access \tcode{y.n}
\end{codeblock}
\end{example}

\pnum
The result of the conversion is determined according to the
following rules:

\begin{itemize}

\item If \tcode{T} is \cv{}~\tcode{std::nullptr_t}, the result is a
null pointer constant\iref{conv.ptr}.
\begin{note}
Since the conversion does not access the object to which the glvalue refers,
there is no side effect even if \tcode{T} is volatile-qualified\iref{intro.execution}, and
the glvalue can refer to an inactive member of a union\iref{class.union}.
\end{note}

\item Otherwise, if \tcode{T} has a class
type, the conversion copy-initializes the result object from
the glvalue.

\item Otherwise, if the object to which the glvalue refers contains an invalid
pointer value\iref{basic.compound}, the behavior is
\impldef{lvalue-to-rvalue conversion of an invalid pointer value}.

\item Otherwise, if the bits in the value representation of
the object to which the glvalue refers
are not valid for the object's type, the behavior is undefined.
\begin{example}
\begin{codeblock}
bool f() {
  bool b = true;
  char c = 42;
  memcpy(&b, &c, 1);
  return b;         // undefined behavior if \tcode{42} is not a valid value representation for \keyword{bool}
}
\end{codeblock}
\end{example}

\item Otherwise, the object indicated by the glvalue is read\iref{defns.access}.
Let \tcode{V} be the value contained in the object.
If \tcode{T} is an integer type,
the prvalue result is
the value of type \tcode{T} congruent\iref{basic.fundamental} to \tcode{V}, and
\tcode{V} otherwise.
\end{itemize}

\pnum
\begin{note}
See also~\ref{basic.lval}.
\end{note}

\rSec2[conv.array]{Array-to-pointer conversion}

\pnum
\indextext{conversion!array-to-pointer}%
\indextext{decay!array|see{conversion, array-to-pointer}}%
\indextext{decay!function|see{conversion, function-to-pointer}}%
An expression $E$ of type ``array of \tcode{N} \tcode{T}'' or ``array
of unknown bound of \tcode{T}'' can be converted to a prvalue of type
``pointer to \tcode{T}''.
If $E$ is a prvalue,
the temporary materialization conversion\iref{conv.rval} is applied.
If the result of $E$ (possibly converted) is an object
whose type is similar to the type of $E$,
the result is a pointer to the first element of the array;
otherwise, the behavior is undefined.

\rSec2[conv.func]{Function-to-pointer conversion}

\pnum
\indextext{conversion!function-to-pointer}%
An lvalue of function type \tcode{T} can be converted to a prvalue of
type ``pointer to \tcode{T}''. The result is a pointer to the
function.
\begin{footnote}
This conversion never applies to non-static member functions because an
lvalue that refers to a non-static member function cannot be obtained.
\end{footnote}

\rSec2[conv.rval]{Temporary materialization conversion}
\indextext{conversion!temporary materialization}%

\pnum
A prvalue of type \tcode{T} can be converted to an xvalue of type \tcode{T}.
This conversion initializes a temporary object\iref{class.temporary} of type \tcode{T} from the prvalue
by evaluating the prvalue with the temporary object as its result object,
and produces an xvalue denoting the temporary object.
\tcode{T} shall be a complete type.
\begin{note}
If \tcode{T} is a class type (or array thereof),
it must have an accessible and non-deleted destructor;
see~\ref{class.dtor}.
\end{note}
\begin{example}
\begin{codeblock}
struct X { int n; };
int k = X().n;      // OK, \tcode{X()} prvalue is converted to xvalue
\end{codeblock}
\end{example}

\rSec2[conv.qual]{Qualification conversions}

\indextext{conversion!qualification|(}%
\pnum
A \defn{qualification-decomposition} of a type \tcode{T}
is a sequence of
$\cv{}_i$ and $P_i$
such that \tcode{T} is
\begin{indented}
``$\cv{}_0$ $P_0$ $\cv{}_1$ $P_1$ $\cdots$ $\cv{}_{n-1}$ $P_{n-1}$ $\cv{}_n$ \tcode{U}'' for $n \geq 0$,
\end{indented}
where
each $\cv{}_i$ is a set of cv-qualifiers\iref{basic.type.qualifier}, and
each $P_i$ is
``pointer to''\iref{dcl.ptr},
``pointer to member of class $C_i$ of type''\iref{dcl.mptr},
``array of $N_i$'', or
``array of unknown bound of''\iref{dcl.array}.
If $P_i$ designates an array,
the cv-qualifiers $\cv{}_{i+1}$ on the element type are also taken as
the cv-qualifiers $\cv{}_i$ of the array.
\begin{example}
The type denoted by the \grammarterm{type-id} \tcode{const int **}
has three qualification-decompositions,
taking \tcode{U}
as ``\keyword{int}'',
as ``pointer to \tcode{\keyword{const} \keyword{int}}'', and
as ``pointer to pointer to \tcode{\keyword{const} \keyword{int}}''.
\end{example}

\pnum
\indextext{type!similar|see{similar types}}%
Two types \tcode{T1} and \tcode{T2} are \defnx{similar}{similar types} if
they have qualification-decompositions with the same $n$
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
The \defnadj{qualification-combined}{type} of two types \tcode{T1} and \tcode{T2}
is the type \tcode{T3}
similar to \tcode{T1} whose qualification-decomposition is such that:
\begin{itemize}
\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$, and
\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 \keyword{const} is added to every $\cv{}^3_k$ for $0 < k < i$,
\end{itemize}
where $\cv{}^j_i$ and $P^j_i$ are the components of
the qualification-decomposition of $\tcode{T}j$.
A prvalue of type \tcode{T1}
can be converted to type \tcode{T2}
if the qualification-combined type of \tcode{T1} and \tcode{T2} is \tcode{T2}.
\begin{note}
If a program could assign a pointer of type \tcode{T**} to a pointer of
type \keyword{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';
  char* pc;
  const char** pcc = &pc;       // \#1: not allowed
  *pcc = &c;
  *pc = 'C';                    // \#2: modifies a const object
}
\end{codeblock}
\end{note}
\begin{note}
Given similar types \tcode{T1} and \tcode{T2}, this
construction ensures that
both can be converted to the qualification-combined type of \tcode{T1} and \tcode{T2}.
\end{note}

\pnum
\begin{note}
A prvalue of type ``pointer to \cvqual{cv1} \tcode{T}'' can be
converted to a prvalue of type ``pointer to \cvqual{cv2} \tcode{T}'' if
``\cvqual{cv2} \tcode{T}'' is more cv-qualified than ``\cvqual{cv1}
\tcode{T}''.
A prvalue of type ``pointer to member of \tcode{X} of type \cvqual{cv1}
\tcode{T}'' can be converted to a prvalue of type ``pointer to member
of \tcode{X} of type \cvqual{cv2} \tcode{T}'' if ``\cvqual{cv2}
\tcode{T}'' is more cv-qualified than ``\cvqual{cv1} \tcode{T}''.
\end{note}

\pnum
\begin{note}
Function types (including those used in pointer-to-member-function types)
are never cv-qualified\iref{dcl.fct}.
\end{note}
\indextext{conversion!qualification|)}

\rSec2[conv.prom]{Integral promotions}

\pnum
For the purposes of \ref{conv.prom},
a \defnadj{converted}{bit-field} is a prvalue that is the result of
an lvalue-to-rvalue conversion\iref{conv.lval} applied to
a bit-field\iref{class.bit}.

\pnum
\indextext{promotion!integral}%
A prvalue that is not a converted bit-field and has an integer type other than
\keyword{bool}, \keyword{char8_t}, \keyword{char16_t},
\keyword{char32_t}, or \keyword{wchar_t} whose integer conversion
rank\iref{conv.rank} is less than the rank of \keyword{int} can be
converted to a prvalue of type \keyword{int} if \keyword{int} can represent
all the values of the source type; otherwise, the source prvalue can be
converted to a prvalue of type \tcode{\keyword{unsigned} \keyword{int}}.

\pnum
\indextext{type!underlying!enumeration}%
A prvalue of an unscoped enumeration type whose underlying type is not
fixed can be converted to a prvalue of the first of the following
types that can represent all the values of the enumeration\iref{dcl.enum}: \keyword{int},
\tcode{\keyword{unsigned} \keyword{int}}, \tcode{\keyword{long} \keyword{int}}, \tcode{\keyword{unsigned} \keyword{long} \keyword{int}},
\tcode{\keyword{long} \keyword{long} \keyword{int}}, or \tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}. If none of the types in that
list can represent all the values of the enumeration, a prvalue of an unscoped
enumeration type can be converted to a prvalue of the extended integer type with lowest
integer conversion rank\iref{conv.rank} greater than the rank of \tcode{long long}
in which all the values of the enumeration can be represented. If there are
two such extended types, the signed one is chosen.

\pnum
A prvalue of an unscoped enumeration type whose underlying type is
fixed\iref{dcl.enum} can be converted to a prvalue of its underlying type. Moreover,
if integral promotion can be applied to its underlying type, a prvalue of an unscoped
enumeration type whose underlying type is fixed can also be converted to a prvalue of
the promoted underlying type.
\begin{note}
A converted bit-field of enumeration type is treated as
any other value of that type for promotion purposes.
\end{note}

\pnum
A converted bit-field of integral type can be converted
to a prvalue of type \keyword{int} if \keyword{int} can represent all the
values of the bit-field; otherwise, it can be converted to
\tcode{\keyword{unsigned} \keyword{int}} if \tcode{\keyword{unsigned} \keyword{int}} can represent all the
values of the bit-field.

\pnum
\indextext{type!underlying!\idxcode{wchar_t}}%
\indextext{type!underlying!\idxcode{char16_t}}%
\indextext{type!underlying!\idxcode{char32_t}}%
A prvalue of type
\keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, or
\keyword{wchar_t}\iref{basic.fundamental}
(including a converted bit-field that was not
already promoted to \keyword{int} or \tcode{\keyword{unsigned} \keyword{int}}
according to the rules above)
can be converted to a prvalue
of the first of the following types that can represent all the values of
its underlying type:
\keyword{int},
\tcode{\keyword{unsigned} \keyword{int}},
\tcode{\keyword{long} \keyword{int}},
\tcode{\keyword{unsigned} \keyword{long} \keyword{int}},
\tcode{\keyword{long} \keyword{long} \keyword{int}},
\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}, or
its underlying type.

\pnum
\indextext{promotion!bool to int}%
A prvalue of type \keyword{bool} can be converted to a prvalue of type
\keyword{int}, with \keyword{false} becoming zero and \keyword{true} becoming
one.

\pnum
These conversions are called \defnx{integral promotions}{integral promotion}.

\rSec2[conv.fpprom]{Floating-point promotion}

\pnum
\indextext{promotion!floating-point}%
A prvalue of type \keyword{float} can be converted to a prvalue of type
\keyword{double}. The value is unchanged.

\pnum
This conversion is called \defn{floating-point promotion}.

\rSec2[conv.integral]{Integral conversions}

\pnum
\indextext{conversion!integral}%
A prvalue of an integer type can be converted to a prvalue of another
integer type. A prvalue of an unscoped enumeration type can be converted to
a prvalue of an integer type.

\pnum
\indextext{conversion!bool@\tcode{bool}}%
If the destination type is \keyword{bool}, see~\ref{conv.bool}. If the
source type is \keyword{bool}, the value \keyword{false} is converted to
zero and the value \keyword{true} is converted to one.

\pnum
\indextext{conversion!to unsigned}%
\indextext{conversion!to signed}%
Otherwise, the result is the unique value of the destination type
that is congruent to the source integer modulo $2^N$,
where $N$ is the width of the destination type.

\pnum
The conversions allowed as integral promotions are excluded from the set
of integral conversions.

\rSec2[conv.double]{Floating-point conversions}

\pnum
\indextext{conversion!floating-point}%
A prvalue of floating-point type can be converted to a prvalue of
another floating-point type
with a greater or equal conversion rank\iref{conv.rank}.
A prvalue of standard floating-point type can be converted to
a prvalue of another standard floating-point type.

\pnum
If the source value can be exactly
represented in the destination type, the result of the conversion is
that exact representation. If the source value is between two adjacent
destination values, the result of the conversion is an
\impldef{result of inexact floating-point conversion} choice of either of those values.
Otherwise, the behavior is undefined.

\pnum
The conversions allowed as floating-point promotions are excluded from
the set of floating-point conversions.

\rSec2[conv.fpint]{Floating-integral conversions}

\pnum
\indextext{conversion!floating to integral}%
A prvalue of a floating-point type can be converted to a prvalue of an
integer type. The conversion truncates; that is, the fractional part is
discarded.
\indextext{value!undefined unrepresentable integral}%
The behavior is undefined if the truncated value cannot be represented
in the destination type.
\begin{note}
If the destination type is \keyword{bool}, see~\ref{conv.bool}.
\end{note}

\pnum
\indextext{conversion!integral to floating}%
\indextext{truncation}%
\indextext{rounding}%
A prvalue of an integer type or of an unscoped enumeration type can be converted to
a prvalue of a floating-point type. The result is exact if possible. If the value being
converted is in the range of values that can be represented but the value cannot be
represented exactly, it is an \impldef{value of result of inexact integer to
floating-point conversion} choice of either the next lower or higher representable
value.
\begin{note}
Loss of precision occurs if the integral value cannot be represented
exactly as a value of the floating-point type.
\end{note}
If the value being converted is
outside the range of values that can be represented, the behavior is undefined. If the
source type is \keyword{bool}, the value \keyword{false} is converted to zero and the value
\keyword{true} is converted to one.

\rSec2[conv.ptr]{Pointer conversions}

\pnum
\indextext{conversion!pointer}%
\indextext{null pointer conversion|see{conversion, null pointer}}%
\indextext{pointer!zero|see{value, null pointer}}%
\indextext{value!null pointer}%
A \defnx{null pointer constant}{constant!null pointer} is an integer literal\iref{lex.icon} with
value zero
or a prvalue of type \tcode{std::nullptr_t}. A null pointer constant can be
converted to a pointer type; the
result is the null pointer value of that type\iref{basic.compound} and is
distinguishable from every other value of
object pointer or function pointer
type.
Such a conversion is called a \defnx{null pointer conversion}{conversion!null pointer}.
The conversion of a null pointer constant to a pointer to
cv-qualified type is a single conversion, and not the sequence of a
pointer conversion followed by a qualification
conversion\iref{conv.qual}. A null pointer constant of integral type
can be converted to a prvalue of type \tcode{std::nullptr_t}.
\begin{note}
The resulting prvalue is not a null pointer value.
\end{note}

\pnum
A prvalue of type ``pointer to \cv{} \tcode{T}'', where \tcode{T}
is an object type, can be converted to a prvalue of type ``pointer to
\cv{} \keyword{void}''.
The pointer value\iref{basic.compound} is unchanged by this conversion.

\pnum
A prvalue \tcode{v} of type ``pointer to \cv{} \tcode{D}'', where \tcode{D}
is a complete class type, can be converted to a prvalue of type ``pointer to
\cv{} \tcode{B}'', where \tcode{B} is a base class\iref{class.derived}
of \tcode{D}. If \tcode{B} is an
inaccessible\iref{class.access} or
ambiguous\iref{class.member.lookup} base class of \tcode{D}, a program
that necessitates this conversion is ill-formed.
If \tcode{v} is a null pointer value,
the result is a null pointer value.
Otherwise,
if \tcode{B} is a virtual base class of \tcode{D}
or is a base class of a virtual base class of \tcode{D} and
\tcode{v} does not point to an object
whose type is similar\iref{conv.qual} to \tcode{D} and
that is
within its lifetime or
within its period of construction or destruction\iref{class.cdtor},
the behavior is undefined.
Otherwise,
the result is a pointer to the base class subobject of
the derived class object.

\rSec2[conv.mem]{Pointer-to-member conversions}

\pnum
\indextext{conversion!pointer-to-member}%
\indextext{null member pointer conversion|see{conversion, null member pointer}}%
\indextext{constant!null pointer}%
A null pointer constant\iref{conv.ptr} can be converted to a
pointer-to-member
type; the result is the \defnx{null member pointer value}{value!null member pointer}
of that type and is distinguishable from any pointer to member not
created from a null pointer constant.
Such a conversion is called a \defnx{null member pointer conversion}{conversion!null member pointer}.
The conversion of a null pointer
constant to a pointer to member of cv-qualified type is a single
conversion, and not the sequence of a pointer-to-member conversion
followed by a qualification conversion\iref{conv.qual}.

\pnum
A prvalue of type ``pointer to member of \tcode{B} of type \cv{}
\tcode{T}'', where \tcode{B} is a class type, can be converted to
a prvalue of type ``pointer to member of \tcode{D} of type \cv{}
\tcode{T}'', where \tcode{D} is a complete class derived\iref{class.derived}
from \tcode{B}. If \tcode{B} is an
inaccessible\iref{class.access},
ambiguous\iref{class.member.lookup}, or virtual\iref{class.mi} base
class of \tcode{D}, or a base class of a virtual base class of
\tcode{D}, a program that necessitates this conversion is ill-formed.
If class \tcode{D} does not contain the original member and
is not a base class of the class containing the original member,
the behavior is undefined. Otherwise,
the result of the conversion refers to the same member as the pointer to
member before the conversion took place, but it refers to the base class
member as if it were a member of the derived class. The result refers to
the member in \tcode{D}'s instance of \tcode{B}. Since the result has
type ``pointer to member of \tcode{D} of type \cv{} \tcode{T}'',
indirection through it with a \tcode{D} object is valid. The result is the same
as if indirecting through the pointer to member of \tcode{B} with the
\tcode{B} subobject of \tcode{D}. The null member pointer value is
converted to the null member pointer value of the destination
type.
\begin{footnote}
The rule for conversion of pointers to members (from pointer to member
of base to pointer to member of derived) appears inverted compared to
the rule for pointers to objects (from pointer to derived to pointer to
base)\iref{conv.ptr,class.derived}. This inversion is
necessary to ensure type safety. Note that a pointer to member is not
an object pointer or a function pointer
and the rules for conversions
of such pointers do not apply to pointers to members.
\indextext{conversion!pointer-to-member!\idxcode{void*}}%
In particular, a pointer to member cannot be converted to a
\tcode{\keyword{void}*}.
\end{footnote}

\rSec2[conv.fctptr]{Function pointer conversions}

\pnum
\indextext{conversion!function pointer}%
A prvalue of type ``pointer to \keyword{noexcept} function''
can be converted to a prvalue of type ``pointer to function''.
The result is a pointer to the function.
A prvalue of type ``pointer to member of type \keyword{noexcept} function''
can be converted to a prvalue of type ``pointer to member of type function''.
The result designates the member function.

\begin{example}
\begin{codeblock}
void (*p)();
void (**pp)() noexcept = &p;    // error: cannot convert to pointer to \keyword{noexcept} function

struct S { typedef void (*p)(); operator p(); };
void (*q)() noexcept = S();     // error: cannot convert to pointer to \keyword{noexcept} function
\end{codeblock}
\end{example}

\rSec2[conv.bool]{Boolean conversions}

\pnum
\indextext{conversion!boolean}%
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member
type can be converted to a prvalue of type \keyword{bool}. A zero value, null
pointer value, or null member pointer value is converted to \keyword{false}; any
other value is converted to \keyword{true}.

\indextext{conversion!standard|)}

\rSec1[expr.arith.conv]{Usual arithmetic conversions}

\pnum
Many binary operators that expect operands of arithmetic or enumeration
type cause conversions and yield result types in a similar way. The
purpose is to yield a common type, which is also the type of the result.
This pattern is called the \defnx{usual arithmetic conversions}{conversion!usual arithmetic},
which are defined as follows:

\begin{itemize}
\item The lvalue-to-rvalue conversion\iref{conv.lval}
is applied to each operand and
the resulting prvalues are used in place of the original operands
for the remainder of this section.
\item If either operand is of scoped enumeration type\iref{dcl.enum}, no conversions
are performed; if the other operand does not have the same type, the expression is
ill-formed.
\item Otherwise, if one operand is of enumeration type and the other operand is
of a different enumeration type or a floating-point type, the expression is
ill-formed.
\item Otherwise, if either operand is of floating-point type,
the following rules are applied:
\begin{itemize}
\item
If both operands have the same type, no further conversion is performed.
\item
Otherwise, if one of the operands is of a non-floating-point type,
that operand is converted to the type of
the operand with the floating-point type.
\item
Otherwise, if the floating-point conversion ranks\iref{conv.rank} of
the types of the operands are ordered but not equal,
then the operand of the type with the lesser floating-point conversion rank
is converted to the type of the other operand.
\item
Otherwise, if the floating-point conversion ranks of the types of
the operands are equal,
then the operand with the lesser floating-point conversion subrank\iref{conv.rank}
is converted to the type of the other operand.
\item
Otherwise, the expression is ill-formed.
\end{itemize}
\item Otherwise, each operand is converted to a common type \tcode{C}.
The integral promotion rules\iref{conv.prom} are used
to determine a type \tcode{T1} and type \tcode{T2} for each operand.
\begin{footnote}
As a consequence, operands of type \keyword{bool}, \keyword{char8_t}, \keyword{char16_t},
\keyword{char32_t}, \keyword{wchar_t}, or of enumeration type are converted
to some integral type.
\end{footnote}
Then the following rules are applied to determine \tcode{C}:

\begin{itemize}

\item If \tcode{T1} and \tcode{T2} are the same type, \tcode{C} is that type.

\item Otherwise, if \tcode{T1} and \tcode{T2} are both signed integer types or
are both unsigned integer types,
\tcode{C} is the type with greater rank.

\item Otherwise, let \tcode{U} be the unsigned integer type and
\tcode{S} be the signed integer type.
\begin{itemize}
\item If \tcode{U} has rank greater than or equal to the rank of \tcode{S},
\tcode{C} is \tcode{U}.
\item Otherwise, if \tcode{S} can represent all of the values of \tcode{U},
\tcode{C} is \tcode{S}.
\item Otherwise,
\tcode{C} is the unsigned integer type corresponding to \tcode{S}.
\end{itemize}
\end{itemize}
\end{itemize}

\rSec1[expr.prim]{Primary expressions}%
\indextext{expression!primary|(}

\rSec2[expr.prim.grammar]{Grammar}

\begin{bnf}
\nontermdef{primary-expression}\br
    literal\br
    \keyword{this}\br
    \terminal{(} expression \terminal{)}\br
    id-expression\br
    lambda-expression\br
    fold-expression\br
    requires-expression\br
    splice-expression
\end{bnf}

\rSec2[expr.prim.literal]{Literals}

\pnum
\indextext{literal}%
\indextext{constant}%
The type of a \grammarterm{literal}
is determined based on its form as specified in \ref{lex.literal}.
A \grammarterm{string-literal} is an lvalue
designating a corresponding string literal object\iref{lex.string},
a \grammarterm{user-defined-literal}
has the same value category
as the corresponding operator call expression described in \ref{lex.ext},
and any other \grammarterm{literal} is a prvalue.

\rSec2[expr.prim.this]{This}

\pnum
\indextext{\idxcode{this}}%
The keyword \keyword{this} names a pointer to the object for which an implicit object member
function\iref{class.mfct.non.static} is invoked or a non-static data member's
initializer\iref{class.mem} is evaluated.

\pnum
The \defnadj{current}{class} at a program point is
the class associated with the innermost class scope containing that point.
\begin{note}
A \grammarterm{lambda-expression} does not introduce a class scope.
\end{note}

\pnum
If the expression \tcode{this}
appears within the predicate of a contract assertion\iref{basic.contract.general}
(including as the result of an implicit transformation\iref{expr.prim.id.general}
and including in the bodies of nested \grammarterm{lambda-expression}s)
and the current class
encloses the contract assertion,
\keyword{const} is combined with the \grammarterm{cv-qualifier-seq}
used to generate the resulting type (see below).

\pnum
If a declaration declares a member function or member function template of a
class \tcode{X}, the expression \keyword{this} is a prvalue of type ``pointer to
\grammarterm{cv-qualifier-seq} \tcode{X}''
wherever \tcode{X} is the current class
between the optional
\grammarterm{cv-qualifier-seq} and the end of the \grammarterm{function-definition},
\grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear within
the declaration of
a static or explicit object member function
of the current class (although its type and value category
are defined within such member functions as they are within an implicit object
member function).
\begin{note}
This is because declaration matching does not
occur until the complete declarator is known.
\end{note}
\begin{note}
In a \grammarterm{trailing-return-type},
the class being defined is not required to be complete
for purposes of class member access\iref{expr.ref}.
Class members declared later are not visible.
\begin{example}
\begin{codeblock}
struct A {
  char g();
  template<class T> auto f(T t) -> decltype(t + g())
    { return t + g(); }
};
template auto A::f(int t) -> decltype(t + g());
\end{codeblock}
\end{example}
\end{note}

\pnum
Otherwise, if a \grammarterm{member-declarator} declares a non-static data
member\iref{class.mem} of a class \tcode{X}, the expression \keyword{this} is
a prvalue of type ``pointer to \tcode{X}''
wherever \tcode{X} is the current class
within the
optional default member initializer\iref{class.mem}.

\pnum
The expression \keyword{this} shall not appear in any other context.
\begin{example}
\begin{codeblock}
class Outer {
  int a[sizeof(*this)];                 // error: not inside a member function
  unsigned int sz = sizeof(*this);      // OK, in default member initializer

  void f() {
    int b[sizeof(*this)];               // OK

    struct Inner {
      int c[sizeof(*this)];             // error: not inside a member function of \tcode{Inner}
    };
  }
};
\end{codeblock}
\end{example}

\rSec2[expr.prim.paren]{Parentheses}

\pnum
\indextext{expression!parenthesized}%
A parenthesized expression \tcode{($E$)}
is a primary expression whose type, result, and value category are identical to those of $E$.
The parenthesized expression can be used in exactly the same contexts as
those where $E$ can be used, and with the same
meaning, except as otherwise indicated.

\rSec2[expr.prim.id]{Names}

\rSec3[expr.prim.id.general]{General}

\begin{bnf}
\nontermdef{id-expression}\br
    unqualified-id\br
    qualified-id\br
    pack-index-expression
\end{bnf}

\pnum
\indextext{name}%
An \grammarterm{id-expression} is a restricted form of a
\grammarterm{primary-expression}.
\begin{note}
An \grammarterm{id-expression} can appear after \tcode{.} and \tcode{->}
operators\iref{expr.ref}.
\end{note}

\pnum
If an \grammarterm{id-expression} $E$ denotes
a non-static non-type member of some class \tcode{C} at a point where
the current class\iref{expr.prim.this} is \tcode{X} and
\begin{itemize}
\item
$E$ is potentially evaluated or
\tcode{C} is \tcode{X} or a base class of \tcode{X}, and
\item
$E$ is not the \grammarterm{id-expression} of
a class member access expression\iref{expr.ref}, and
\item
$E$ is not the \grammarterm{id-expression} of
a \grammarterm{reflect-expression}\iref{expr.reflect}, and
\item
if $E$ is a \grammarterm{qualified-id},
$E$ is not the un-parenthesized operand of
the unary \tcode{\&} operator\iref{expr.unary.op},
\end{itemize}
the \grammarterm{id-expression} is transformed into
a class member access expression using \tcode{(*this)} as the object expression.
If this transformation occurs
in the predicate of a precondition assertion of a constructor of \tcode{X}
or a postcondition assertion of a destructor of \tcode{X},
the expression is ill-formed.
\begin{note}
If \tcode{C} is not \tcode{X} or a base class of \tcode{X},
the class member access expression is ill-formed.
Also, if the \grammarterm{id-expression} occurs within
a static or explicit object member function,
the class member access is ill-formed.
\end{note}
This transformation does not apply in
the template definition context\iref{temp.dep.type}.
\begin{example}
\begin{codeblock}
struct C {
  bool b;
  C() pre(b)                // error
      pre(&this->b)         // OK
      pre(sizeof(b) > 0);   // OK, \tcode{b} is not potentially evaluated.
};
\end{codeblock}
\end{example}

\pnum
If an \grammarterm{id-expression} $E$ denotes
a variant member $M$ of an anonymous union\iref{class.union.anon} $U$:
\begin{itemize}
\item
If $U$ is a non-static data member,
$E$ refers to $M$ as a member of the lookup context of the terminal name of $E$
(after any implicit transformation to
a class member access expression).
\begin{example}
\tcode{o.x} is interpreted as \tcode{o.$u$.x},
where $u$ names the anonymous union member.
\end{example}
\item
Otherwise, $E$ is interpreted as a class member access\iref{expr.ref}
that designates the member subobject $M$ of
the anonymous union variable for $U$.
\begin{note}
Under this interpretation, $E$ no longer denotes a non-static data member.
\end{note}
\begin{example}
\tcode{N::x} is interpreted as \tcode{N::$u$.x},
where $u$ names the anonymous union variable.
\end{example}
\end{itemize}

\pnum
An \grammarterm{id-expression} or \grammarterm{splice-expression}
that designates a non-static data member or
implicit object member function of a class can only be used:
\begin{itemize}
\item as part of a class member access
(after any implicit transformation (see above))
in which the
object expression
refers to the member's class
or a class derived from
that class, or

\item to form a pointer to member\iref{expr.unary.op}, or

\item if that \grammarterm{id-expression} or \grammarterm{splice-expression}
designates a non-static data member
and it appears in an unevaluated operand.
\begin{example}
\begin{codeblock}
struct S {
  int m;
};
int i = sizeof(S::m);           // OK
int j = sizeof(S::m + 42);      // OK
int S::*k = &[:^^S::m:];        // OK
\end{codeblock}
\end{example}
\end{itemize}

\pnum
A \grammarterm{splice-expression} that designates a direct base class relationship
shall appear only as the second operand of a class member access.

\pnum
For an \grammarterm{id-expression} that denotes an overload set,
overload resolution is performed
to select a unique function\iref{over.match,over.over}.
\begin{note}
A program cannot refer to a function
with a trailing \grammarterm{requires-clause}
whose \grammarterm{constraint-expression} is not satisfied,
because such functions are never selected by overload resolution.
\begin{example}
\begin{codeblock}
template<typename T> struct A {
  static void f(int) requires false;
};

void g() {
  A<int>::f(0);                         // error: cannot call \tcode{f}
  void (*p1)(int) = A<int>::f;          // error: cannot take the address of \tcode{f}
  decltype(A<int>::f)* p2 = nullptr;    // error: the type \tcode{decltype(A<int>::f)} is invalid
}
\end{codeblock}
In each case, the constraints of \tcode{f} are not satisfied.
In the declaration of \tcode{p2},
those constraints need to be satisfied
even though
\tcode{f} is an unevaluated operand\iref{term.unevaluated.operand}.
\end{example}
\end{note}

\rSec3[expr.prim.id.unqual]{Unqualified names}

\begin{bnf}
\nontermdef{unqualified-id}\br
    identifier\br
    operator-function-id\br
    conversion-function-id\br
    literal-operator-id\br
    \terminal{\~} type-name\br
    \terminal{\~} computed-type-specifier\br
    template-id
\end{bnf}

\pnum
\indextext{identifier}%
An \grammarterm{identifier} is only
an \grammarterm{id-expression} if it has
been suitably declared\iref{dcl}
or if it appears as part of a \grammarterm{declarator-id}\iref{dcl.decl}.
\begin{note}
For \grammarterm{operator-function-id}{s}, see~\ref{over.oper}; for
\grammarterm{conversion-function-id}{s}, see~\ref{class.conv.fct}; for
\grammarterm{literal-operator-id}{s}, see~\ref{over.literal}; for
\grammarterm{template-id}{s}, see~\ref{temp.names}.
A \grammarterm{type-name} or \grammarterm{computed-type-specifier}
prefixed by \tcode{\~} denotes the destructor of the type so named;
see~\ref{expr.prim.id.dtor}.
\end{note}

\pnum
A \defn{component name} of an \grammarterm{unqualified-id} $U$ is
\begin{itemize}
\item
$U$ if it is a name or
\item
the component name of
the \grammarterm{template-id} or \grammarterm{type-name} of $U$, if any.
\end{itemize}
\begin{note}
Other constructs that contain names to look up can have several
component names\iref{expr.prim.id.qual,dcl.type.simple,dcl.type.elab,
dcl.mptr,namespace.udecl,temp.param,temp.names,temp.res}.
\end{note}
The \defnadj{terminal}{name} of a construct is
the component name of that construct that appears lexically last.

\pnum
The result is the entity denoted by
the \grammarterm{unqualified-id}\iref{basic.lookup.unqual}.

\pnum
If
\begin{itemize}
\item
the \grammarterm{unqualified-id}
appears in a \grammarterm{lambda-expression}
at program point $P$,
\item
the entity is a local entity\iref{basic.pre}
or a variable declared by an \grammarterm{init-capture}\iref{expr.prim.lambda.capture},
\item
naming the entity within the \grammarterm{compound-statement} of
the innermost enclosing \grammarterm{lambda-expression} of $P$,
but not in an unevaluated operand, would refer to an entity captured by copy
in some intervening \grammarterm{lambda-expression}, and
\item
$P$ is in the function parameter scope,
but not the \grammarterm{parameter-declaration-clause},
of the innermost such \grammarterm{lambda-expression} $E$,
\end{itemize}
then
the type of the expression is
the type of a class member access expression\iref{expr.ref}
naming the non-static data member
that would be declared for such a capture
in the object parameter\iref{dcl.fct} of the function call operator of $E$.
\begin{note}
If $E$ is not declared \keyword{mutable},
the type of such an identifier will typically be \keyword{const} qualified.
\end{note}

\begin{example}
\begin{codeblock}
void f() {
  float x, &r = x;

  [=]() -> decltype((x)) {      // lambda returns \tcode{float const\&} because this lambda is not \tcode{mutable} and
                                // \tcode{x} is an lvalue
    decltype(x) y1;             // \tcode{y1} has type \tcode{float}
    decltype((x)) y2 = y1;      // \tcode{y2} has type \tcode{float const\&}
    decltype(r) r1 = y1;        // \tcode{r1} has type \tcode{float\&}
    decltype((r)) r2 = y2;      // \tcode{r2} has type \tcode{float const\&}
    return y2;
  };

  [=](decltype((x)) y) {
    decltype((x)) z = x;        // OK, \tcode{y} has type \tcode{float\&}, \tcode{z} has type \tcode{float const\&}
  };

  [=] {
    [](decltype((x)) y) {};     // OK, lambda takes a parameter of type \tcode{float const\&}

    [x=1](decltype((x)) y) {
      decltype((x)) z = x;      // OK, \tcode{y} has type \tcode{int\&}, \tcode{z} has type \tcode{int const\&}
    };
  };
}
\end{codeblock}
\end{example}

\pnum
Otherwise,
if the \grammarterm{unqualified-id}
names a coroutine parameter,
the type of the expression is
that of the copy of the parameter\iref{dcl.fct.def.coroutine},
and the result is that copy.

\pnum
Otherwise,
if the \grammarterm{unqualified-id}
names a result binding\iref{dcl.contract.res}
attached to a function
with return type \tcode{U},
\begin{itemize}
\item
if \tcode{U} is ``reference to \tcode{T}'',
then the type of the expression is
\tcode{const T};
\item
otherwise,
the type of the expression is \tcode{const U}.
\end{itemize}

\pnum
Otherwise,
if the \grammarterm{unqualified-id}
appears in the predicate of a contract assertion $C$\iref{basic.contract}
and the entity is
\begin{itemize}
\item
a variable
declared outside of $C$
of object type \tcode{T},
\item
a variable or template parameter
declared outside of $C$
of type ``reference to \tcode{T}'', or
\item
a structured binding
of type \tcode{T}
whose corresponding variable
is declared outside of $C$,
\end{itemize}
then the type of the expression is \keyword{const}~\tcode{T}.

\pnum
\begin{example}
\begin{codeblock}
int n = 0;
struct X { bool m(); };

struct Y {
  int z = 0;

  void f(int i, int* p, int& r, X x, X* px)
    pre (++n)       // error: attempting to modify const lvalue
    pre (++i)       // error: attempting to modify const lvalue
    pre (++(*p))    // OK
    pre (++r)       // error: attempting to modify const lvalue
    pre (x.m())     // error: calling non-const member function
    pre (px->m())   // OK
    pre ([=,&i,*this] mutable {
      ++n;          // error: attempting to modify const lvalue
      ++i;          // error: attempting to modify const lvalue
      ++p;          // OK, refers to member of closure type
      ++r;          // OK, refers to non-reference member of closure type
      ++this->z;    // OK, captured \tcode{*\keyword{this}}
      ++z;          // OK, captured \tcode{*\keyword{this}}
      int j = 17;
      [&]{
        int k = 34;
        ++i;    // error: attempting to modify const lvalue
        ++j;    // OK
        ++k;    // OK
      }();
      return true;
    }());

  template <int N, int& R, int* P>
  void g()
    pre(++N)        // error: attempting to modify prvalue
    pre(++R)        // error: attempting to modify const lvalue
    pre(++(*P));    // OK

  int h()
    post(r : ++r)   // error: attempting to modify const lvalue
    post(r: [=] mutable {
       ++r;         // OK, refers to member of closure type
       return true;
     }());

  int& k()
    post(r : ++r);  // error: attempting to modify const lvalue
};
\end{codeblock}
\end{example}

\pnum
Otherwise, if the entity is a template parameter object for
a template parameter of type \tcode{T}\iref{temp.param},
the type of the expression is \tcode{const T}.

\pnum
In all other cases, the type of the expression is the type of the entity.

\pnum
\begin{note}
The type will be adjusted as described in \ref{expr.type}
if it is cv-qualified or is a reference type.
\end{note}

\pnum
The expression is an xvalue if it is move-eligible (see below);
an lvalue
if the entity is a
function,
variable,
structured binding\iref{dcl.struct.bind},
result binding\iref{dcl.contract.res},
data member, or
template parameter object;
and a prvalue otherwise\iref{basic.lval};
it is a bit-field if the identifier designates a bit-field.

\pnum
If an \grammarterm{id-expression} $E$
appears in the predicate of
a function contract assertion attached to a function \placeholder{f}
and denotes
a function parameter of \placeholder{f}
and the implementation introduces any temporary objects
to hold the value of that parameter as specified in \ref{class.temporary},
\begin{itemize}
\item
if the contract assertion
is a precondition assertion
and the evaluation of the precondition assertion
is sequenced before the initialization of the parameter object,
$E$ refers to the most recently initialized such temporary object, and
\item
if the contract assertion
is a postcondition assertion,
it is unspecified whether $E$ refers to
one of the temporary objects or the parameter object;
the choice is consistent within a single evaluation of a postcondition assertion.
\end{itemize}

\pnum
If an \grammarterm{id-expression} $E$
names a result binding
in a postcondition assertion
and the implementation introduces any temporary objects
to hold the result object as specified in \ref{class.temporary},
and the postcondition assertion
is sequenced before the initialization of the result object\iref{expr.call},
$E$ refers to the most recently initialized such temporary object.

\pnum
An \defnadj{implicitly movable}{entity} is
a variable with automatic storage duration
that is either a non-volatile object or
an rvalue reference to a non-volatile object type.
An \grammarterm{id-expression} or
\grammarterm{splice-expression}\iref{expr.prim.splice}
is \defn{move-eligible} if
\begin{itemize}
\item
it designates an implicitly movable entity,
\item
it is the (possibly parenthesized)
operand of a \tcode{return}\iref{stmt.return} or
\keyword{co_return}\iref{stmt.return.coroutine} statement or
of a \grammarterm{throw-expression}\iref{expr.throw}, and
\item
each intervening scope between
the declaration of the entity and
the innermost enclosing scope of the expression
is a block scope and,
for a \grammarterm{throw-expression},
is not the block scope of
a \grammarterm{try-block} or \grammarterm{function-try-block}.
\end{itemize}

\rSec3[expr.prim.id.qual]{Qualified names}

\indextext{operator!scope resolution}%
\indextext{\idxcode{::}|see{operator, scope resolution}}%
%
\begin{bnf}
\nontermdef{qualified-id}\br
    nested-name-specifier \opt{\keyword{template}} unqualified-id
\end{bnf}

\indextext{operator!scope resolution}%
\indextext{name hiding}%
%
\begin{bnf}
\nontermdef{nested-name-specifier}\br
    \terminal{::}\br
    type-name \terminal{::}\br
    namespace-name \terminal{::}\br
    computed-type-specifier \terminal{::}\br
    splice-scope-specifier \terminal{::}\br
    nested-name-specifier identifier \terminal{::}\br
    nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::}
\end{bnf}
\begin{bnf}
\nontermdef{splice-scope-specifier}\br
    splice-specifier\br
    \opt{\keyword{template}} splice-specialization-specifier
\end{bnf}

\pnum
\indextext{component name}%
The component names of a \grammarterm{qualified-id} are those of
its \grammarterm{nested-name-specifier} and \grammarterm{unqualified-id}.
The component names of a \grammarterm{nested-name-specifier} are
its \grammarterm{identifier} (if any) and those of its
\grammarterm{type-name},
\grammarterm{namespace-name},
\grammarterm{simple-template-id}, and/or
\grammarterm{nested-name-specifier}.

\pnum
A \grammarterm{splice-specifier} or
\grammarterm{splice-specialization-specifier}
that is not followed by \tcode{::}
is never interpreted as part of a \grammarterm{splice-scope-specifier}.
The keyword \keyword{template} may only be omitted
from the form
\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::}
when the \grammarterm{splice-specialization-specifier}
is preceded by \keyword{typename}.
\begin{example}
\begin{codeblock}
template<int V>
struct TCls {
  static constexpr int s = V;
  using type = int;
};

int v1 = [:^^TCls<1>:]::s;
int v2 = template [:^^TCls:]<2>::s;             // OK, \keyword{template} binds to \grammarterm{splice-scope-specifier}
typename [:^^TCls:]<3>::type v3 = 3;            // OK, \keyword{typename} binds to the qualified name
template [:^^TCls:]<3>::type v4 = 4;            // OK, \keyword{template} binds to the \grammarterm{splice-scope-specifier}
typename template [:^^TCls:]<3>::type v5 = 5;   // OK, same as \tcode{v3}
[:^^TCls:]<3>::type v6 = 6;                     // error: unexpected \tcode{<}
\end{codeblock}
\end{example}

\pnum
A \grammarterm{nested-name-specifier} is \defn{declarative} if it is part of
\begin{itemize}
\item
a \grammarterm{class-head-name}\iref{class.pre},
\item
an \grammarterm{enum-head-name}\iref{dcl.enum},
\item
a \grammarterm{qualified-id}
that is the \grammarterm{id-expression}
of a \grammarterm{declarator-id}\iref{dcl.decl.general},
\item
an \grammarterm{elaborated-type-specifier}
of an explicit instantiation\iref{temp.explicit}, or
\item
a declarative \grammarterm{nested-name-specifier}.
\end{itemize}
A declarative \grammarterm{nested-name-specifier}
shall not have a \grammarterm{computed-type-specifier} or
a \grammarterm{splice-scope-specifier}.
A declaration that uses a declarative \grammarterm{nested-name-specifier}
shall be a friend declaration or
inhabit a scope that contains the entity being redeclared or specialized.

\pnum
The entity designated by a \grammarterm{nested-name-specifier}
is determined as follows:
\begin{itemize}
\item
The \grammarterm{nested-name-specifier} \tcode{::} designates
the global namespace.
\item
A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier}
designates the same type designated by the \grammarterm{computed-type-specifier},
which shall be a class or enumeration type.
\item
For a \grammarterm{nested-name-specifier} of
the form \tcode{\grammarterm{splice-specifier} ::},
the \grammarterm{splice-specifier} shall designate
a class or enumeration type or a namespace.
The \grammarterm{nested-name-specifier} designates the same entity
as the \grammarterm{splice-specifier}.
\item
For a \grammarterm{nested-name-specifier} of
the form
\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::},
the \grammarterm{splice-specifier} of
the \grammarterm{splice-specialization-specifier} shall designate
a class template or an alias template $T$.
Letting $S$ be the specialization of $T$
corresponding to the template argument list of
the \grammarterm{splice-specialization-specifier},
$S$ shall either be a class template specialization or
an alias template specialization that denotes a class or enumeration type.
The \grammarterm{nested-name-specifier} designates the underlying entity of $S$.
\item
If a \grammarterm{nested-name-specifier} $N$
is declarative and
has a \grammarterm{simple-template-id} with a template argument list $A$
that involves a template parameter,
let $T$ be the template nominated by $N$ without $A$.
$T$ shall be a class template.
\begin{itemize}
\item
If $A$ is the template argument list\iref{temp.arg} of
the corresponding \grammarterm{template-head} $H$\iref{temp.mem},
$N$ designates the primary template of $T$;
$H$ shall be equivalent to
the \grammarterm{template-head} of $T$\iref{temp.over.link}.
\item
Otherwise, $N$ designates the partial specialization\iref{temp.spec.partial} of $T$
whose template argument list is equivalent to $A$\iref{temp.over.link};
the program is ill-formed if no such partial specialization exists.
\end{itemize}
\item
Any other \grammarterm{nested-name-specifier} designates
the entity denotes by its
\grammarterm{type-name},
\grammarterm{namespace-name},
\grammarterm{identifier}, or
\grammarterm{simple-template-id}.
If the \grammarterm{nested-name-specifier} is not declarative,
the entity shall not be a template.
\end{itemize}

\pnum
A \grammarterm{qualified-id} shall not be of the form
\grammarterm{nested-name-specifier} \opt{\keyword{template}} \tcode{\~}
\grammarterm{computed-type-specifier}
nor of the form
\grammarterm{computed-type-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}.

\pnum
The result of a \grammarterm{qualified-id} $Q$ is
the entity it denotes\iref{basic.lookup.qual}.

\pnum
If $Q$ appears
in the predicate of a contract assertion $C$\iref{basic.contract}
and the entity is
\begin{itemize}
\item
a variable
declared outside of $C$
of object type \tcode{T},
\item
a variable
declared outside of $C$
of type ``reference to \tcode{T}'', or
\item
a structured binding of type \tcode{T}
whose corresponding variable
is declared outside of $C$,
\end{itemize}
then the type of the expression is \keyword{const}~\tcode{T}.


\pnum
Otherwise, the type of the expression is the type of the result.

\pnum
The result is an lvalue if the member is
\begin{itemize}
\item
a function other than a non-static member function,
\item
a non-static member function
if $Q$ is the operand of a unary \tcode{\&} operator,
\item
a variable,
\item
a structured binding\iref{dcl.struct.bind}, or
\item
a data member,
\end{itemize}
and a prvalue otherwise.

\rSec3[expr.prim.pack.index]{Pack indexing expression}

\begin{bnf}
\nontermdef{pack-index-expression}\br
    id-expression \terminal{...} \terminal{[} constant-expression \terminal{]}
\end{bnf}

\pnum
The \grammarterm{id-expression} $P$ in a \grammarterm{pack-index-expression}
shall be an \grammarterm{identifier} that denotes a pack.

\pnum
The \grammarterm{constant-expression} shall be
a converted constant expression\iref{expr.const.const} of type \tcode{std::size_t}
whose value $V$, termed the index,
is such that $0 \le V < \tcode{sizeof...($P$)}$.

\pnum
A \grammarterm{pack-index-expression} is a pack expansion\iref{temp.variadic}.

\pnum
\begin{note}
A \grammarterm{pack-index-expression} denotes
the $V^\text{th}$ element of the pack.
\end{note}

\rSec3[expr.prim.id.dtor]{Destruction}

\pnum
\indextext{expression!destructor call}%
\indextext{expression!pseudo-destructor call}%
An \grammarterm{id-expression} that denotes the destructor of a type \tcode{T}
names the destructor of \tcode{T}
if \tcode{T} is a class type\iref{class.dtor},
otherwise the \grammarterm{id-expression} is said
to name a \defn{pseudo-destructor}.

\pnum
If the \grammarterm{id-expression} names a pseudo-destructor,
\tcode{T} shall be a scalar type and
the \grammarterm{id-expression} shall appear
as the right operand of a class member access\iref{expr.ref} that forms
the \grammarterm{postfix-expression} of a function call\iref{expr.call}.
\begin{note}
Such a call ends the lifetime of the object\iref{expr.call,basic.life}.
\end{note}

\pnum
\begin{example}
\begin{codeblock}
struct C { };
void f() {
  C * pc = new C;
  using C2 = C;
  pc->C::~C2();     // OK, destroys \tcode{*pc}
  C().C::~C();      // undefined behavior: temporary of type \tcode{C} destroyed twice
  using T = int;
  0 .T::~T();       // OK, no effect
  0.T::~T();        // error: \tcode{0.T} is a \grammarterm{user-defined-floating-point-literal}\iref{lex.ext}
}
\end{codeblock}
\end{example}

\rSec2[expr.prim.lambda]{Lambda expressions}%

\rSec3[expr.prim.lambda.general]{General}%
\indextext{expression!lambda|(}

\begin{bnf}
\nontermdef{lambda-expression}\br
    lambda-introducer \opt{attribute-specifier-seq} lambda-declarator compound-statement\br
    lambda-introducer \terminal{<} template-parameter-list \terminal{>} \opt{requires-clause} \opt{attribute-specifier-seq}\br
    \bnfindent lambda-declarator compound-statement
\end{bnf}

\begin{bnf}
\nontermdef{lambda-introducer}\br
    \terminal{[} \opt{lambda-capture} \terminal{]}
\end{bnf}

\begin{bnf}
\nontermdef{lambda-declarator}\br
    lambda-specifier-seq \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type}\br
    \bnfindent \opt{function-contract-specifier-seq}\br
    noexcept-specifier \opt{attribute-specifier-seq} \opt{trailing-return-type} \opt{function-contract-specifier-seq}\br
    \opt{trailing-return-type} \opt{function-contract-specifier-seq}\br
    \terminal{(} parameter-declaration-clause \terminal{)} \opt{lambda-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq}\br
    \bnfindent \opt{trailing-return-type} \opt{requires-clause} \opt{function-contract-specifier-seq}
\end{bnf}

\begin{bnf}
\nontermdef{lambda-specifier}\br
    \keyword{consteval}\br
    \keyword{constexpr}\br
    \keyword{mutable}\br
    \keyword{static}
\end{bnf}

\begin{bnf}
\nontermdef{lambda-specifier-seq}\br
    lambda-specifier \opt{lambda-specifier-seq}
\end{bnf}

\pnum
A \grammarterm{lambda-expression} provides
a concise way to create a simple function object.
\begin{example}
\begin{codeblock}
#include <algorithm>
#include <cmath>
void abssort(float* x, unsigned N) {
  std::sort(x, x + N, [](float a, float b) { return std::abs(a) < std::abs(b); });
}
\end{codeblock}
\end{example}

\pnum
A \grammarterm{lambda-expression} is a prvalue
whose result object is called the \defn{closure object}.
\begin{note}
A closure object behaves like a function
object\iref{function.objects}.
\end{note}

\pnum
An ambiguity can arise
because a \grammarterm{requires-clause} can end in
an \grammarterm{attribute-specifier-seq},
which collides with
the \grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}.
In such cases,
any attributes are treated as
\grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}.
\begin{note}
Such ambiguous cases cannot have valid semantics
because the constraint expression would not have type \keyword{bool}.
\begin{example}
\begin{codeblock}
auto x = []<class T> requires T::operator int [[some_attribute]] (int) { }
\end{codeblock}
\end{example}
\end{note}

\pnum
A \grammarterm{lambda-specifier-seq}
shall contain at most one of each \grammarterm{lambda-specifier} and
shall not contain both \keyword{constexpr} and \keyword{consteval}.
If the \grammarterm{lambda-declarator} contains
an explicit object parameter\iref{dcl.fct},
then no \grammarterm{lambda-specifier} in the \grammarterm{lambda-specifier-seq}
shall be \keyword{mutable} or \keyword{static}.
The \grammarterm{lambda-specifier-seq} shall not contain
both \keyword{mutable} and \keyword{static}.
If the \grammarterm{lambda-specifier-seq} contains \keyword{static},
there shall be no \grammarterm{lambda-capture}.
\begin{note}
The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}.
\end{note}

\pnum
A \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause}
is the \grammarterm{parameter-declaration-clause} of
the \grammarterm{lambda-expression}{'s} \grammarterm{lambda-declarator}, if any,
or empty otherwise.
If the \grammarterm{lambda-declarator}
does not include a \grammarterm{trailing-return-type},
it is considered to be \tcode{-> \keyword{auto}}.
\begin{note}
In that case, the return type is deduced from \keyword{return} statements
as described in \ref{dcl.spec.auto}.
\end{note}
\begin{example}
\begin{codeblock}
auto x1 = [](int i) { return i; };      // OK, return type is \tcode{int}
auto x2 = []{ return { 1, 2 }; };       // error: deducing return type from \grammarterm{braced-init-list}
int j;
auto x3 = [&]()->auto&& { return j; };  // OK, return type is \tcode{int\&}
\end{codeblock}
\end{example}

\pnum
A lambda is a \defn{generic lambda}
if the \grammarterm{lambda-expression}
has any generic parameter type placeholders\iref{dcl.spec.auto}, or
if the lambda has a \grammarterm{template-parameter-list}.
\begin{example}
\begin{codeblock}
auto x = [](int i, auto a) { return i; };               // OK, a generic lambda
auto y = [](this auto self, int i) { return i; };       // OK, a generic lambda
auto z = []<class T>(int i) { return i; };              // OK, a generic lambda
\end{codeblock}
\end{example}

\rSec3[expr.prim.lambda.closure]{Closure types}%

\pnum
The type of a \grammarterm{lambda-expression} (which is also the type of the
closure object) is a unique, unnamed non-union class type,
called the \defn{closure type},
whose properties are described below.

\pnum
The closure type is incomplete
until the end of its corresponding \grammarterm{compound-statement}.

\pnum
The closure type is declared in the smallest block
scope, class scope, or namespace scope that contains the corresponding
\grammarterm{lambda-expression}.
\begin{note}
This determines the set of namespaces and
classes associated with the closure type\iref{basic.lookup.argdep}. The parameter
types of a \grammarterm{lambda-declarator} do not affect these associated namespaces and
classes.
\end{note}

\pnum
The closure type is not an aggregate type\iref{dcl.init.aggr}
and is not \tcode{final}\iref{class.pre};
it is a structural type\iref{term.structural.type} if and only if
the lambda has no \grammarterm{lambda-capture}.
An implementation may define the closure type differently from what
is described below provided this does not alter the observable behavior of the program
other than by changing:
\begin{itemize}
\item the size and/or alignment of the closure type,
\item whether the closure type is trivially copyable\iref{class.prop}, or
\item whether the closure type is a standard-layout class\iref{class.prop}.
\end{itemize}

An implementation shall not add members of rvalue reference type to the closure
type.

\pnum
The closure type for a \grammarterm{lambda-expression} has a public
inline function call operator (for a non-generic lambda) or
function call operator template (for a generic lambda)\iref{over.call}
whose parameters and return type
are those of the \grammarterm{lambda-expression}{'s}
\grammarterm{parameter-declaration-clause} and \grammarterm{trailing-return-type}
respectively, and whose
\grammarterm{template-parameter-list} consists of
the specified \grammarterm{template-parameter-list}, if any.
The function call operator or the function call operator template are
direct members of the closure type.
The \grammarterm{requires-clause} of the function call operator template
is the \grammarterm{requires-clause} immediately following
\tcode{<}~\grammarterm{template-parameter-list}{}~\tcode{>}, if any.
The trailing \grammarterm{requires-clause} of the function call operator
or operator template is the \grammarterm{requires-clause}
of the \grammarterm{lambda-declarator}, if any.
\begin{note}
The function call operator template for a generic lambda can be
an abbreviated function template\iref{dcl.fct}.
\end{note}
\begin{example}
\begin{codeblock}
auto glambda = [](auto a, auto&& b) { return a < b; };
bool b = glambda(3, 3.14);                                      // OK

auto vglambda = [](auto printer) {
  return [=](auto&& ... ts) {                                   // OK, \tcode{ts} is a function parameter pack
    printer(std::forward<decltype(ts)>(ts)...);

    return [=]() {
      printer(ts ...);
    };
  };
};
auto p = vglambda( [](auto v1, auto v2, auto v3)
                   { std::cout << v1 << v2 << v3; } );
auto q = p(1, 'a', 3.14);                                       // OK, outputs \tcode{1a3.14}
q();                                                            // OK, outputs \tcode{1a3.14}

auto fact = [](this auto self, int n) -> int {                  // OK, explicit object parameter
  return (n <= 1) ? 1 : n * self(n-1);
};
std::cout << fact(5);                                           // OK, outputs 120
\end{codeblock}
\end{example}

\pnum
Given a lambda with a \grammarterm{lambda-capture},
the type of the explicit object parameter, if any,
of the lambda's function call operator
(possibly instantiated from a function call operator template)
shall be either:
\begin{itemize}
\item
the closure type,
\item
a class type publicly and unambiguously derived from the closure type, or
\item
a reference to a possibly cv-qualified such type.
\end{itemize}
\begin{example}
\begin{codeblock}
struct C {
  template <typename T>
  C(T);
};

void func(int i) {
  int x = [=](this auto&&) { return i; }();     // OK
  int y = [=](this C) { return i; }();          // error
  int z = [](this C) { return 42; }();          // OK
}
\end{codeblock}
\end{example}

\pnum
The function call operator or operator template is
a static member function or static member function template\iref{class.static.mfct}
if the \grammarterm{lambda-expression}'s
\grammarterm{parameter-declaration-clause} is followed by \keyword{static}.
Otherwise, it is
a non-static member function or member function template\iref{class.mfct.non.static}
that is declared
\keyword{const}\iref{class.mfct.non.static} if and only if the
\grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not
followed by \keyword{mutable} and
the \grammarterm{lambda-declarator} does not contain
an explicit object parameter.
It is neither virtual nor declared \tcode{volatile}.
Any \grammarterm{noexcept-specifier} or \grammarterm{function-contract-specifier}\iref{dcl.contract.func}
specified on a \grammarterm{lambda-expression}
applies to the corresponding function call operator or operator template.
An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
to the type of the corresponding function call operator or operator template.
An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-expression}
preceding a \grammarterm{lambda-declarator}
appertains to the corresponding function call operator or operator template.
The function call operator or any given operator template specialization
is a constexpr function if either
the corresponding \grammarterm{lambda-expression}{'s}
\grammarterm{parameter-declaration-clause}
is followed by \keyword{constexpr} or \keyword{consteval}, or
it is constexpr-suitable\iref{dcl.constexpr}.
It is an immediate function\iref{dcl.constexpr}
if the corresponding \grammarterm{lambda-expression}{'s}
\grammarterm{parameter-declaration-clause} is followed by \keyword{consteval}.
\begin{example}
\begin{codeblock}
auto ID = [](auto a) { return a; };
static_assert(ID(3) == 3);                      // OK

struct NonLiteral {
  NonLiteral(int n) : n(n) { }
  int n;
};
static_assert(ID(NonLiteral{3}).n == 3);        // error
\end{codeblock}
\end{example}

\pnum
\begin{example}
\begin{codeblock}
auto monoid = [](auto v) { return [=] { return v; }; };
auto add = [](auto m1) constexpr {
  auto ret = m1();
  return [=](auto m2) mutable {
    auto m1val = m1();
    auto plus = [=](auto m2val) mutable constexpr
                   { return m1val += m2val; };
    ret = plus(m2());
    return monoid(ret);
  };
};
constexpr auto zero = monoid(0);
constexpr auto one = monoid(1);
static_assert(add(one)(zero)() == one());       // OK

// Since \tcode{two} below is not declared \keyword{constexpr}, an evaluation of its \tcode{constexpr} member function call operator
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
// in a constant expression.
auto two = monoid(2);
assert(two() == 2); // OK, not a constant expression.
static_assert(add(one)(one)() == two());        // error: \tcode{two()} is not a constant expression
static_assert(add(one)(one)() == monoid(2)());  // OK
\end{codeblock}
\end{example}

\pnum
\begin{note}
The function call operator or operator template can be constrained\iref{temp.constr.decl}
by a \grammarterm{type-constraint}\iref{temp.param},
a \grammarterm{requires-clause}\iref{temp.pre},
or a trailing \grammarterm{requires-clause}\iref{dcl.decl}.
\begin{example}
\begin{codeblock}
template <typename T> concept C1 = @\commentellip@;
template <std::size_t N> concept C2 = @\commentellip@;
template <typename A, typename B> concept C3 = @\commentellip@;

auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)>
         (T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> {
  // \tcode{T2} is constrained by a \grammarterm{type-constraint}.
  // \tcode{T1} and \tcode{T2} are constrained by a \grammarterm{requires-clause}, and
  // \tcode{T2} and the type of \tcode{a4} are constrained by a trailing \grammarterm{requires-clause}.
};
\end{codeblock}
\end{example}
\end{note}

\pnum
If all potential references
to a local entity implicitly captured by a \grammarterm{lambda-expression} $L$
occur within the function contract assertions\iref{dcl.contract.func}
of the call operator or operator template of $L$
or within \grammarterm{assertion-statement}s\iref{stmt.contract.assert}
within the body of $L$,
the program is ill-formed.
\begin{note}
Adding a contract assertion to an existing \Cpp{} program cannot
cause additional captures.
\end{note}
\begin{example}
\begin{codeblock}
static int i = 0;

void test() {
  auto f1 = [=] pre(i > 0) {};  // OK, no local entities are captured.

  int i = 1;
  auto f2 = [=] pre(i > 0) {};  // error: cannot implicitly capture \tcode{i} here
  auto f3 = [i] pre(i > 0) {};  // OK, \tcode{i} is captured explicitly.

  auto f4 = [=] {
    contract_assert(i > 0);     // error: cannot implicitly capture \tcode{i} here
  };

  auto f5 = [=] {
    contract_assert(i > 0);     // OK, \tcode{i} is referenced elsewhere.
    (void)i;
  };

  auto f6 = [=] pre(                // \#1
    []{
      bool x = true;
      return [=]{ return x; }();    // OK, \#1 captures nothing.
    }()) {};

  bool y = true;
  auto f7 = [=] pre([=]{ return y; }());    // error: outer capture of \tcode{y} is invalid.
}
\end{codeblock}
\end{example}


\pnum
The closure type for a non-generic \grammarterm{lambda-expression} with no
\grammarterm{lambda-capture}
and no explicit object parameter\iref{dcl.fct}
whose constraints (if any) are satisfied
has a conversion function to pointer to
function with \Cpp{} language linkage\iref{dcl.link} having
the same parameter and return types as the closure type's function call operator.
The conversion is to ``pointer to \keyword{noexcept} function''
if the function call operator
has a non-throwing exception specification.
If the function call operator is a static member function,
then the value returned by this conversion function is
a pointer to the function call operator.
Otherwise, the value returned by this conversion function
is a pointer to a function \tcode{F} that, when invoked,
has the same effect as invoking the closure type's function call operator
on a default-constructed instance of the closure type.
\tcode{F} is a constexpr function
if the function call operator is a constexpr function
and is an immediate function
if the function call operator is an immediate function.

\pnum
For a generic lambda with no \grammarterm{lambda-capture}
and no explicit object parameter\iref{dcl.fct},
the closure type has a
conversion function template to
pointer to function. The conversion function template has the same invented
template parameter list, and the pointer to function has the same
parameter types, as the function call operator template.  The return type of
the pointer to function shall behave as if it were a
\grammarterm{decltype-specifier} denoting the return type of the corresponding
function call operator template specialization.

\pnum
\begin{note}
If the generic lambda has no \grammarterm{trailing-return-type} or
the \grammarterm{trailing-return-type} contains a placeholder type, return type
deduction of the corresponding function call operator template specialization
has to be done. The corresponding specialization is that instantiation of the
function call operator template with the same template arguments as those
deduced for the conversion function template.  Consider the following:
\begin{codeblock}
auto glambda = [](auto a) { return a; };
int (*fp)(int) = glambda;
\end{codeblock}
The behavior of the conversion function of \tcode{glambda} above is like
that of the following conversion function:
\begin{codeblock}
struct Closure {
  template<class T> auto operator()(T t) const { @\commentellip@ }
  template<class T> static auto lambda_call_operator_invoker(T a) {
    // forwards execution to \tcode{operator()(a)} and therefore has
    // the same return type deduced
    @\commentellip@
  }
  template<class T> using fptr_t =
    decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);

  template<class T> operator fptr_t<T>() const
    { return &lambda_call_operator_invoker; }
};
\end{codeblock}
\end{note}

\begin{example}
\begin{codeblock}
void f1(int (*)(int))   { }
void f2(char (*)(int))  { }

void g(int (*)(int))    { }     // \#1
void g(char (*)(char))  { }     // \#2

void h(int (*)(int))    { }     // \#3
void h(char (*)(int))   { }     // \#4

auto glambda = [](auto a) { return a; };
f1(glambda);                    // OK
f2(glambda);                    // error: ID is not convertible
g(glambda);                     // error: ambiguous
h(glambda);                     // OK, calls \#3 since it is convertible from ID
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; };        // OK
\end{codeblock}
\end{example}

\pnum
If the function call operator template is a static member function template,
then the value returned by
any given specialization of this conversion function template is
a pointer to the corresponding function call operator template specialization.
Otherwise,
the value returned by any given specialization of this conversion function
template is a pointer to a function \tcode{F} that, when invoked, has the same
effect as invoking the generic lambda's corresponding function call operator
template specialization on a default-constructed instance of the closure type.
\tcode{F} is a constexpr function
if the corresponding specialization is a constexpr function and
\tcode{F} is an immediate function
if the function call operator template specialization is an immediate function.
\begin{note}
This will result in the implicit instantiation of the generic lambda's body.
The instantiated generic lambda's return type and parameter types need to match
the return type and parameter types of the pointer to function.
\end{note}
\begin{example}
\begin{codeblock}
auto GL = [](auto a) { std::cout << a; return a; };
int (*GL_int)(int) = GL;        // OK, through conversion function template
GL_int(3);                      // OK, same as \tcode{GL(3)}
\end{codeblock}
\end{example}

\pnum
The conversion function or conversion function template is public,
constexpr, non-virtual, non-explicit, const, and has a non-throwing exception
specification\iref{except.spec}.
\begin{example}
\begin{codeblock}
auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
auto C = [](auto a) { return a; };

static_assert(Fwd(C,3) == 3);   // OK

// No specialization of the function call operator template can be constexpr (due to the local static).
auto NC = [](auto a) { static int s; return a; };
static_assert(Fwd(NC,3) == 3);  // error
\end{codeblock}
\end{example}

\pnum
The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields
the \grammarterm{function-body}\iref{dcl.fct.def} of the function call operator,
but it is not within the scope of the closure type.
\begin{example}
\begin{codeblock}
struct S1 {
  int x, y;
  int operator()(int);
  void f() {
    [=]()->int {
      return operator()(this->x + y);   // equivalent to \tcode{S1::operator()(this->x + (*this).y)}
                                        // \keyword{this} has type \tcode{S1*}
    };
  }
};
\end{codeblock}
\end{example}
Unless the \grammarterm{compound-statement} is
that of a \grammarterm{consteval-block-declaration}\iref{dcl.pre},
a variable \mname{func} is implicitly defined at the beginning of
the \grammarterm{compound-statement} of the \grammarterm{lambda-expression},
with semantics as described in~\ref{dcl.fct.def.general}.

\pnum
The closure type associated with a \grammarterm{lambda-expression} has no
default constructor
if the \grammarterm{lambda-expression} has a \grammarterm{lambda-capture}
and a defaulted default constructor otherwise.
It has a defaulted copy constructor and a defaulted move constructor\iref{class.copy.ctor}.
It has a deleted copy assignment operator if the \grammarterm{lambda-expression}
has a \grammarterm{lambda-capture} and defaulted copy and move assignment
operators otherwise\iref{class.copy.assign}.
\begin{note}
These special member functions are implicitly defined as
usual, which can result in them being defined as deleted.
\end{note}

\pnum
The closure type associated with a \grammarterm{lambda-expression} has an
implicitly-declared destructor\iref{class.dtor}.

\pnum
A member of a closure type shall not be
explicitly instantiated\iref{temp.explicit},
explicitly specialized\iref{temp.expl.spec}, or
named in a friend declaration\iref{class.friend}.

\rSec3[expr.prim.lambda.capture]{Captures}%

\begin{bnf}
\nontermdef{lambda-capture}\br
    capture-default\br
    capture-list\br
    capture-default \terminal{,} capture-list
\end{bnf}

\begin{bnf}
\nontermdef{capture-default}\br
    \terminal{\&}\br
    \terminal{=}
\end{bnf}

\begin{bnf}
\nontermdef{capture-list}\br
    capture\br
    capture-list \terminal{,} capture
\end{bnf}

\begin{bnf}
\nontermdef{capture}\br
    simple-capture\br
    init-capture
\end{bnf}

\begin{bnf}
\nontermdef{simple-capture}\br
    identifier \opt{\terminal{...}}\br
    \terminal{\&} identifier \opt{\terminal{...}}\br
    \keyword{this}\br
    \terminal{*} \keyword{this}
\end{bnf}

\begin{bnf}
\nontermdef{init-capture}\br
    \opt{\terminal{...}} identifier initializer\br
    \terminal{\&} \opt{\terminal{...}} identifier initializer
\end{bnf}

\pnum
The body of a \grammarterm{lambda-expression} may refer to local entities
of enclosing scopes by capturing those entities, as described
below.

\pnum
If a \grammarterm{lambda-capture} includes a \grammarterm{capture-default} that
is \tcode{\&}, no identifier in a \grammarterm{simple-capture} of that
\grammarterm{lambda-capture} shall be preceded
by \tcode{\&}. If a \grammarterm{lambda-capture} includes a
\grammarterm{capture-default} that is \tcode{=}, each
\grammarterm{simple-capture} of that \grammarterm{lambda-capture} shall
be of the form
``\tcode{\&} \grammarterm{identifier} \opt{\tcode{...}}'',
``\keyword{this}'',
or ``\tcode{* \keyword{this}}''.
\begin{note}
The form \tcode{[\&,\keyword{this}]} is redundant but accepted
for compatibility with \CppXIV{}.
\end{note}
Ignoring appearances in
\grammarterm{initializer}{s} of \grammarterm{init-capture}{s}, an identifier or
\keyword{this} shall not appear more than once in a
\grammarterm{lambda-capture}.
\begin{example}
\begin{codeblock}
struct S2 { void f(int i); };
void S2::f(int i) {
  [&, i]{ };        // OK
  [&, this, i]{ };  // OK, equivalent to \tcode{[\&, i]}
  [&, &i]{ };       // error: \tcode{i} preceded by \tcode{\&} when \tcode{\&} is the default
  [=, *this]{ };    // OK
  [=, this]{ };     // OK, equivalent to \tcode{[=]}
  [i, i]{ };        // error: \tcode{i} repeated
  [this, *this]{ }; // error: \keyword{this} appears twice
}
\end{codeblock}
\end{example}

\pnum
A \grammarterm{lambda-expression} shall not have
a \grammarterm{capture-default} or \grammarterm{simple-capture}
in its \grammarterm{lambda-introducer}
unless
\begin{itemize}
\item
its innermost enclosing scope is a block scope\iref{basic.scope.block},
\item
it appears within a default member initializer
and its innermost enclosing scope is
the corresponding class scope\iref{basic.scope.class}, or
\item
it appears within a contract assertion
and its innermost enclosing scope
is the corresponding contract-assertion scope\iref{basic.scope.contract}.
\end{itemize}

\pnum
The \grammarterm{identifier} in a \grammarterm{simple-capture}
shall denote a local entity\iref{basic.lookup.unqual,basic.pre}.
The \grammarterm{simple-capture}{s} \keyword{this} and \tcode{* \keyword{this}}
denote the local entity \tcode{*\keyword{this}}.
An entity that is designated by a
\grammarterm{simple-capture}
is said to be \defn{explicitly captured}.

\pnum
If an \grammarterm{identifier} in a \grammarterm{capture} appears
as the \grammarterm{declarator-id} of a parameter of
the \grammarterm{lambda-declarator}'s \grammarterm{parameter-declaration-clause}
or as the name of a template parameter of
the \grammarterm{lambda-expression}'s \grammarterm{template-parameter-list},
the program is ill-formed.
\begin{example}
\begin{codeblock}
void f() {
  int x = 0;
  auto g = [x](int x) { return 0; };    // error: parameter and \grammarterm{capture} have the same name
  auto h = [y = 0]<typename y>(y) { return 0; };    // error: template parameter and \grammarterm{capture}
                                                    // have the same name
}
\end{codeblock}
\end{example}

\pnum
An \grammarterm{init-capture} inhabits
the lambda scope\iref{basic.scope.lambda}
of the \grammarterm{lambda-expression}.
An \grammarterm{init-capture} without ellipsis
behaves as if it declares and explicitly captures a variable of
the form ``\keyword{auto} \grammarterm{init-capture} \tcode{;}'', except that:
\begin{itemize}
\item if the capture is by copy (see below), the non-static data member
declared for the capture and the variable are treated as two different ways
of referring to the same object, which has the lifetime of the non-static
data member, and no additional copy and destruction is performed, and
\item if the capture is by reference, the variable's lifetime ends when the
closure object's lifetime ends.
\end{itemize}
\begin{note}
This enables an \grammarterm{init-capture} like
``\tcode{x = std::move(x)}''; the second ``\tcode{x}'' must bind to a
declaration in the surrounding context.
\end{note}
\begin{example}
\begin{codeblock}
int x = 4;
auto y = [&r = x, x = x+1]()->int {
            r += 2;
            return x+2;
         }();                               // Updates \tcode{::x} to 6, and initializes \tcode{y} to 7.

auto z = [a = 42](int a) { return 1; };     // error: parameter and conceptual local variable
                                            // have the same name
auto counter = [i=0]() mutable -> decltype(i) {     // OK, returns \tcode{int}
  return i++;
};
\end{codeblock}
\end{example}

\pnum
For the purposes of lambda capture,
an expression potentially references local entities as follows:

\begin{itemize}
\item
An \grammarterm{id-expression} that names a local entity
potentially references that entity;
an \grammarterm{id-expression} that names
one or more non-static class members
and does not form a pointer to member\iref{expr.unary.op}
potentially references \tcode{*\keyword{this}}.
\begin{note}
This occurs even if overload resolution
selects a static member function for the \grammarterm{id-expression}.
\end{note}

\item
A \keyword{this} expression potentially references \tcode{*\keyword{this}}.

\item
A \grammarterm{lambda-expression} potentially references
the local entities named by its \grammarterm{simple-capture}{s}.
\end{itemize}

If an expression potentially references a local entity
within a scope in which it is odr-usable\iref{basic.def.odr},
and the expression would be potentially evaluated
if the effect of any enclosing \keyword{typeid} expressions\iref{expr.typeid} were ignored,
the entity is said to be \defnx{implicitly captured}{capture!implicit}
by each intervening \grammarterm{lambda-expression} with an associated
\grammarterm{capture-default} that does not explicitly capture it.
The implicit capture of \tcode{*\keyword{this}} is deprecated when the
\grammarterm{capture-default} is \tcode{=}; see \ref{depr.capture.this}.
\begin{example}
\begin{codeblock}
void f(int, const int (&)[2] = {});         // \#1
void f(const int&, const int (&)[1]);       // \#2
void test() {
  const int x = 17;
  auto g = [](auto a) {
    f(x);                       // OK, calls \#1, does not capture \tcode{x}
  };

  auto g1 = [=](auto a) {
    f(x);                       // OK, calls \#1, captures \tcode{x}
  };

  auto g2 = [=](auto a) {
    int selector[sizeof(a) == 1 ? 1 : 2]{};
    f(x, selector);             // OK, captures \tcode{x}, can call \#1 or \#2
  };

  auto g3 = [=](auto a) {
    typeid(a + x);              // captures \tcode{x} regardless of whether \tcode{a + x} is an unevaluated operand
  };
}
\end{codeblock}
Within \tcode{g1}, an implementation can optimize away
the capture of \tcode{x} as it is not odr-used.
\end{example}
\begin{note}
The set of captured entities is determined syntactically,
and entities are implicitly captured
even if the expression denoting a local entity
is within a discarded statement\iref{stmt.if}.
\begin{example}
\begin{codeblock}
template<bool B>
void f(int n) {
  [=](auto a) {
    if constexpr (B && sizeof(a) > 4) {
      (void)n;                  // captures \tcode{n} regardless of the value of \tcode{B} and \tcode{sizeof(int)}
    }
  }(0);
}
\end{codeblock}
\end{example}
\end{note}

\pnum
An entity is \defn{captured} if it is captured explicitly or implicitly. An entity
captured by a \grammarterm{lambda-expression} is odr-used\iref{term.odr.use} by
the \grammarterm{lambda-expression}.
\begin{note}
As a consequence, if a \grammarterm{lambda-expression}
explicitly captures an entity that is not odr-usable,
the program is ill-formed\iref{basic.def.odr}.
\end{note}
\begin{example}
\indextext{Bond!James Bond}%
\begin{codeblock}
void f1(int i) {
  int const N = 20;
  auto m1 = [=]{
    int const M = 30;
    auto m2 = [i]{
      int x[N][M];              // OK, \tcode{N} and \tcode{M} are not odr-used
      x[0][0] = i;              // OK, \tcode{i} is explicitly captured by \tcode{m2} and implicitly captured by \tcode{m1}
    };
  };
  struct s1 {
    int f;
    void work(int n) {
      int m = n*n;
      int j = 40;
      auto m3 = [this,m] {
        auto m4 = [&,j] {       // error: \tcode{j} not odr-usable due to intervening lambda \tcode{m3}
          int x = n;            // error: \tcode{n} is odr-used but not odr-usable due to intervening lambda \tcode{m3}
          x += m;               // OK, \tcode{m} implicitly captured by \tcode{m4} and explicitly captured by \tcode{m3}
          x += i;               // error: \tcode{i} is odr-used but not odr-usable
                                // due to intervening function and class scopes
          x += f;               // OK, \keyword{this} captured implicitly by \tcode{m4} and explicitly by \tcode{m3}
        };
      };
    }
  };
}

struct s2 {
  double ohseven = .007;
  auto f() {
    return [this] {
      return [*this] {
          return ohseven;       // OK
      };
    }();
  }
  auto g() {
    return [] {
      return [*this] { };       // error: \tcode{*this} not captured by outer \grammarterm{lambda-expression}
    }();
  }
};
\end{codeblock}
\end{example}

\pnum
\begin{note}
Because local entities are not
odr-usable within a default argument\iref{basic.def.odr},
a \grammarterm{lambda-expression} appearing in a default argument
cannot implicitly or explicitly capture any local entity.
Such a \grammarterm{lambda-expression}
can still have an \grammarterm{init-capture} if
any full-expression in its \grammarterm{initializer}
satisfies the constraints of an expression appearing in
a default argument\iref{dcl.fct.default}.
\end{note}
\begin{example}
\begin{codeblock}
void f2() {
  int i = 1;
  void g1(int = ([i]{ return i; })());          // error
  void g2(int = ([i]{ return 0; })());          // error
  void g3(int = ([=]{ return i; })());          // error
  void g4(int = ([=]{ return 0; })());          // OK
  void g5(int = ([]{ return sizeof i; })());    // OK
  void g6(int = ([x=1]{ return x; })());        // OK
  void g7(int = ([x=i]{ return x; })());        // error
}
\end{codeblock}
\end{example}

\pnum
An entity is \defnx{captured by copy}{captured!by copy} if
\begin{itemize}
\item
it is implicitly captured,
the \grammarterm{capture-default} is \tcode{=}, and
the captured entity is not \tcode{*\keyword{this}}, or
\item
it is explicitly captured with a capture that is not of the form
\keyword{this},
\tcode{\&} \grammarterm{identifier} \opt{\tcode{...}}, or
\tcode{\&} \opt{\tcode{...}} \grammarterm{identifier} \grammarterm{initializer}.
\end{itemize}
For each entity captured by copy, an
unnamed non-static data member is declared in the closure type. The declaration order of
these members is unspecified. The type of such a data member is
the referenced type if the entity is a reference to an object,
an lvalue reference to the referenced function type if the entity is a reference to a function, or
the type of the corresponding captured entity otherwise.
A member of an anonymous union shall not be captured by copy.

\pnum
Every \grammarterm{id-expression} within the \grammarterm{compound-statement} of a
\grammarterm{lambda-expression} that is an odr-use\iref{term.odr.use} of an
entity captured by copy is transformed into an access to the corresponding unnamed data
member of the closure type.
\begin{note}
An \grammarterm{id-expression} that is not an odr-use refers to
the original entity, never to a member of the closure type.
However, such
an \grammarterm{id-expression} can still cause the implicit capture of the
entity.
\end{note}
If \tcode{*\keyword{this}} is captured by copy, each expression that odr-uses \tcode{*\keyword{this}} is
transformed to instead refer to the corresponding unnamed data member of the closure type.
\begin{example}
\begin{codeblock}
void f(const int*);
void g() {
  const int N = 10;
  [=] {
    int arr[N];     // OK, not an odr-use, refers to variable with automatic storage duration
    f(&N);          // OK, causes \tcode{N} to be captured; \tcode{\&N} points to
                    // the corresponding member of the closure type
  };
}
\end{codeblock}
\end{example}

\pnum
An entity is \defnx{captured by reference}{captured!by reference} if it is implicitly or explicitly
captured but not captured by copy. It is unspecified whether additional unnamed
non-static data members are declared in the closure type for entities captured by
reference.
If declared, such non-static data members shall be of literal type.
\begin{example}
\begin{codeblock}
// The inner closure type must be a literal type regardless of how reference captures are represented.
static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4);
\end{codeblock}
\end{example}
A bit-field or a member of an anonymous union
shall not be captured by reference.

\pnum
An \grammarterm{id-expression} within
the \grammarterm{compound-statement} of a \grammarterm{lambda-expression}
that is an odr-use of a reference captured by reference
refers to the entity to which the captured reference is bound and
not to the captured reference.
\begin{note}
The validity of such captures is determined by
the lifetime of the object to which the reference refers,
not by the lifetime of the reference itself.
\end{note}
\begin{example}
\begin{codeblock}
auto h(int &r) {
  return [&] {
    ++r;            // Valid after \tcode{h} returns if the lifetime of the
                    // object to which \tcode{r} is bound has not ended
  };
}
\end{codeblock}
\end{example}

\pnum
If a \grammarterm{lambda-expression} \tcode{m2} captures an entity and that entity is
captured by an immediately enclosing \grammarterm{lambda-expression}
\tcode{m1}, then
\tcode{m2}'s capture is transformed as follows:
\begin{itemize}
\item If \tcode{m1} captures the entity by copy,
\tcode{m2} captures the corresponding
non-static data member of \tcode{m1}'s closure type;
if \tcode{m1} is not \keyword{mutable}, the non-static data member is considered to be const-qualified.
\item If \tcode{m1} captures the entity by reference,
\tcode{m2} captures the same
entity captured by \tcode{m1}.
\end{itemize}
\begin{example}
The nested \grammarterm{lambda-expression}s and invocations below will output
\tcode{123234}.
\begin{codeblock}
int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable {
  auto m2 = [a, b, &c]() mutable {
    std::cout << a << b << c;
    a = 4; b = 4; c = 4;
  };
  a = 3; b = 3; c = 3;
  m2();
};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c;
\end{codeblock}
\end{example}

\pnum
The entities that are
captured by copy are used to direct-initialize each corresponding non-static data member
of the resulting closure object, and the non-static data members corresponding to the
\grammarterm{init-capture}{s} are initialized as indicated by the corresponding
\grammarterm{initializer} (which may be copy- or direct-initialization). (For array members, the array elements are
direct-initialized in increasing subscript order.) These initializations are performed
when the \grammarterm{lambda-expression} is evaluated and
in the (unspecified) order in which the non-static data members are declared.
\begin{note}
This ensures that the destructions will occur in the reverse order of the constructions.
\end{note}

\pnum
\begin{note}
If a non-reference entity is implicitly or explicitly captured by reference,
invoking the function call operator of the corresponding \grammarterm{lambda-expression}
after the lifetime of the entity has ended is likely to result in undefined behavior.
\end{note}

\pnum
A \grammarterm{simple-capture} containing an ellipsis is a pack
expansion\iref{temp.variadic}.
\indextext{init-capture pack@\fakegrammarterm{init-capture} pack}%
An \grammarterm{init-capture} containing an ellipsis is a pack
expansion that declares an
\grammarterm{init-capture} pack\iref{temp.variadic}.
\begin{example}
\begin{codeblock}
template<class... Args>
void f(Args... args) {
  auto lm = [&, args...] { return g(args...); };
  lm();

  auto lm2 = [...xs=std::move(args)] { return g(xs...); };
  lm2();
}
\end{codeblock}
\end{example}
\indextext{expression!lambda|)}

\rSec2[expr.prim.fold]{Fold expressions}%
\indextext{expression!fold|(}

\pnum
A fold expression performs a fold of a
pack\iref{temp.variadic} over a binary operator.

\begin{bnf}
\nontermdef{fold-expression}\br
    \terminal{(} cast-expression fold-operator \terminal{...} \terminal{)}\br
    \terminal{(} \terminal{...} fold-operator cast-expression \terminal{)}\br
    \terminal{(} cast-expression fold-operator \terminal{...} fold-operator cast-expression \terminal{)}
\end{bnf}

\begin{bnf}
%% Ed. note: character protrusion would misalign operators with leading `-`.
\microtypesetup{protrusion=false}
\nontermdef{fold-operator} \textnormal{one of}\br
    \terminal{+ }\quad\terminal{- }\quad\terminal{* }\quad\terminal{/ }\quad\terminal{\% }\quad\terminal{\caret{} }\quad\terminal{\& }\quad\terminal{| }\quad\terminal{<< }\quad\terminal{>> }\br
    \terminal{+=}\quad\terminal{-=}\quad\terminal{*=}\quad\terminal{/=}\quad\terminal{\%=}\quad\terminal{\caret=}\quad\terminal{\&=}\quad\terminal{|=}\quad\terminal{<<=}\quad\terminal{>>=}\quad\terminal{=}\br
    \terminal{==}\quad\terminal{!=}\quad\terminal{< }\quad\terminal{> }\quad\terminal{<=}\quad\terminal{>=}\quad\terminal{\&\&}\quad\terminal{||}\quad\terminal{,  }\quad\terminal{.* }\quad\terminal{->*}
\end{bnf}

\pnum
\indextext{fold!unary}%
An expression of the form
\tcode{(...} \placeholder{op} \tcode{e)}
where \placeholder{op} is a \grammarterm{fold-operator}
is called a \defn{unary left fold}.
An expression of the form
\tcode{(e} \placeholder{op} \tcode{...)}
where \placeholder{op} is a \grammarterm{fold-operator}
is called a \defn{unary right fold}.
Unary left folds and unary right folds
are collectively called \defnx{unary folds}{unary fold}.
In a unary fold,
the \grammarterm{cast-expression}
shall contain an unexpanded pack\iref{temp.variadic}.

\pnum
\indextext{fold!binary}%
An expression of the form
\tcode{(e1} \placeholder{op1} \tcode{...} \placeholder{op2} \tcode{e2)}
where \placeholder{op1} and \placeholder{op2} are \grammarterm{fold-operator}{s}
is called a \defn{binary fold}.
In a binary fold,
\placeholder{op1} and \placeholder{op2}
shall be the same \grammarterm{fold-operator},
and either \tcode{e1}
shall contain an unexpanded pack
or \tcode{e2}
shall contain an unexpanded pack,
but not both.
If \tcode{e2} contains an unexpanded pack,
the expression is called a \defn{binary left fold}.
If \tcode{e1} contains an unexpanded pack,
the expression is called a \defn{binary right fold}.
\begin{example}
\begin{codeblock}
template<typename ...Args>
bool f(Args ...args) {
  return (true && ... && args); // OK
}

template<typename ...Args>
bool f(Args ...args) {
  return (args + ... + args);   // error: both operands contain unexpanded packs
}
\end{codeblock}
\end{example}

\pnum
A fold expression is a pack expansion.
\indextext{expression!fold|)}%

\rSec2[expr.prim.req]{Requires expressions}

\rSec3[expr.prim.req.general]{General}
\indextext{expression!requires|(}%

\pnum
A \grammarterm{requires-expression} provides a concise way to express
requirements on template arguments
that can be checked by name lookup\iref{basic.lookup}
or by checking properties of types and expressions.

\begin{bnf}
\nontermdef{requires-expression}\br
    \keyword{requires} \opt{requirement-parameter-list} requirement-body
\end{bnf}

\begin{bnf}
\nontermdef{requirement-parameter-list}\br
    \terminal{(} parameter-declaration-clause \terminal{)}
\end{bnf}

\begin{bnf}
\microtypesetup{protrusion=false}
\nontermdef{requirement-body}\br
    \terminal{\{} requirement-seq \terminal{\}}
\end{bnf}

\begin{bnf}
\nontermdef{requirement-seq}\br
    requirement \opt{requirement-seq}
\end{bnf}

\begin{bnf}
\nontermdef{requirement}\br
    simple-requirement\br
    type-requirement\br
    compound-requirement\br
    nested-requirement
\end{bnf}

\pnum
A \grammarterm{requires-expression} is a prvalue of type \tcode{bool}
whose value is described below.

\pnum
\begin{example}
A common use of \grammarterm{requires-expression}s is to define
requirements in concepts such as the one below:
\begin{codeblock}
template<typename T>
  concept R = requires (T i) {
    typename T::type;
    {*i} -> std::@\libconcept{convertible_to}@<const typename T::type&>;
  };
\end{codeblock}
A \grammarterm{requires-expression} can also be used in a
\grammarterm{requires-clause}\iref{temp.pre} as a way of writing ad hoc
constraints on template arguments such as the one below:
\begin{codeblock}
template<typename T>
  requires requires (T x) { x + x; }
    T add(T a, T b) { return a + b; }
\end{codeblock}
The first \keyword{requires} introduces the
\grammarterm{requires-clause}, and the second
introduces the \grammarterm{requires-expression}.
\end{example}

\pnum
A \grammarterm{requires-expression} may introduce local parameters using a
\grammarterm{parameter-declaration-clause}.
A local parameter of a \grammarterm{requires-expression} shall not have a
default argument.
The type of such a parameter is determined as specified for
a function parameter in~\ref{dcl.fct}.
These parameters have no linkage, storage, or lifetime; they are only used
as notation for the purpose of defining \grammarterm{requirement}s.
The \grammarterm{parameter-declaration-clause} of a
\grammarterm{requirement-parameter-list}
shall not terminate with an ellipsis.
\begin{example}
\begin{codeblock}
template<typename T>
concept C = requires(T t, ...) {    // error: terminates with an ellipsis
  t;
};
template<typename T>
concept C2 = requires(T p[2]) {
  (decltype(p))nullptr;             // OK, \tcode{p} has type ``pointer to \tcode{T}''
};
\end{codeblock}
\end{example}

\pnum
The substitution of template arguments into a \grammarterm{requires-expression}
can result in
the formation of invalid types or expressions in the immediate context of
its \grammarterm{requirement}s\iref{temp.deduct.general} or
the violation of the semantic constraints of those \grammarterm{requirement}s.
In such cases, the \grammarterm{requires-expression} evaluates to \keyword{false};
it does not cause the program to be ill-formed.
The substitution and semantic constraint checking
proceeds in lexical order and stops when a condition that
determines the result of the \grammarterm{requires-expression} is encountered.
If substitution (if any) and semantic constraint checking succeed,
the \grammarterm{requires-expression} evaluates to \keyword{true}.
\begin{note}
If a \grammarterm{requires-expression} contains invalid types or expressions in
its \grammarterm{requirement}s, and it does not appear within the declaration of a templated
entity, then the program is ill-formed.
\end{note}
If the substitution of template arguments into a \grammarterm{requirement}
would always result in a substitution failure, the program is ill-formed;
no diagnostic required.
\begin{example}
\begin{codeblock}
template<typename T> concept C =
requires {
  new decltype((void)T{});      // ill-formed, no diagnostic required
};
\end{codeblock}
\end{example}

\rSec3[expr.prim.req.simple]{Simple requirements}
\indextext{requirement!simple}%

\begin{bnf}
\nontermdef{simple-requirement}\br
    expression \terminal{;}
\end{bnf}

\pnum
A \grammarterm{simple-requirement} asserts
the validity of an \grammarterm{expression}.
The \grammarterm{expression} is an unevaluated operand.
\begin{note}
The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false}
if substitution of template arguments into the \grammarterm{expression} fails.
\end{note}
\begin{example}
\begin{codeblock}
template<typename T> concept C =
  requires (T a, T b) {
    a + b;          // \tcode{C<T>} is \tcode{true} if \tcode{a + b} is a valid expression
  };
\end{codeblock}
\end{example}

\pnum
A \grammarterm{requirement} that starts with a \keyword{requires} token
is never interpreted as a \grammarterm{simple-requirement}.
\begin{note}
This simplifies distinguishing between a \grammarterm{simple-requirement}
and a \grammarterm{nested-requirement}.
\end{note}

\rSec3[expr.prim.req.type]{Type requirements}
\indextext{requirement!type}%

\begin{bnf}
\nontermdef{type-requirement}\br
    \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;}\br
    \keyword{typename} splice-specifier \terminal{;}\br
    \keyword{typename} splice-specialization-specifier \terminal{;}
\end{bnf}

\pnum
A \grammarterm{type-requirement} asserts the validity of a type.
The component names of a \grammarterm{type-requirement} are those of its
\grammarterm{nested-name-specifier} (if any) and
\grammarterm{type-name} (if any).
\begin{note}
The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false}
if substitution of template arguments fails.
\end{note}
\begin{example}
\begin{codeblock}
template<typename T, typename T::type = 0> struct S;
template<typename T> using Ref = T&;

template<typename T> concept C = requires {
  typename T::inner;        // required nested member name
  typename S<T>;            // required valid\iref{temp.names} \grammarterm{template-id}; fails if \tcode{T::type} does not exist as a type
                            // to which \tcode{0} can be implicitly converted
  typename Ref<T>;          // required alias template substitution, fails if \tcode{T} is \tcode{void}
  typename [:T::r1:];       // fails if \tcode{T::r1} is not a reflection of a type
  typename [:T::r2:]<int>;  // fails if \tcode{T::r2} is not a reflection of a template \tcode{Z} for which \tcode{Z<int>} is a type
};
\end{codeblock}
\end{example}

\pnum
A \grammarterm{type-requirement} that names a class template specialization
does not require that type to be complete\iref{term.incomplete.type}.

\rSec3[expr.prim.req.compound]{Compound requirements}
\indextext{requirement!compound}%

\begin{bnf}
\nontermdef{compound-requirement}\br
    \terminal{\{} expression \terminal{\}} \opt{\keyword{noexcept}} \opt{return-type-requirement} \terminal{;}
\end{bnf}

\begin{bnf}
\nontermdef{return-type-requirement}\br
    \terminal{->} type-constraint
\end{bnf}

\pnum
A \grammarterm{compound-requirement} asserts properties
of the \grammarterm{expression} $E$.
The \grammarterm{expression} is an unevaluated operand.
Substitution
of template arguments (if any) and verification of
semantic properties proceed in the following order:

\begin{itemize}
\item
Substitution of template arguments (if any)
into the \grammarterm{expression} is performed.

\item
If the \keyword{noexcept} specifier is present,
$E$ shall not be a potentially-throwing expression\iref{except.spec}.

\item
If the \grammarterm{return-type-requirement} is present, then:

\begin{itemize}
\item
Substitution of template arguments (if any)
into the \grammarterm{return-type-requirement} is performed.

\item
The immediately-declared constraint\iref{temp.param}
of the \grammarterm{type-constraint} for \tcode{\keyword{decltype}((E))}
shall be satisfied.
\end{itemize}
\begin{example}
Given concepts \tcode{C} and \tcode{D},
\begin{codeblock}
requires {
  { E1 } -> C;
  { E2 } -> @D<A$_1$, $\cdots$, A$_n$>@;
};
\end{codeblock}
is equivalent to
\begin{codeblock}
requires {
  E1; requires C<decltype((E1))>;
  E2; requires @D<decltype((E2)), A$_1$, $\cdots$, A$_n$>@;
};
\end{codeblock}
(including in the case where $n$ is zero).
\end{example}
\end{itemize}
\pnum
\begin{example}
\begin{codeblock}
template<typename T> concept C1 = requires(T x) {
  {x++};
};
\end{codeblock}
The \grammarterm{compound-requirement} in \tcode{C1}
requires that \tcode{x++} is a valid expression.
It is equivalent to the \grammarterm{simple-requirement}
\tcode{x++;}.

\begin{codeblock}
template<typename T> concept C2 = requires(T x) {
  {*x} -> std::@\libconcept{same_as}@<typename T::inner>;
};
\end{codeblock}

The \grammarterm{compound-requirement} in \tcode{C2}
requires that \tcode{*x} is a valid expression,
that \tcode{typename T::inner} is a valid type, and
that \tcode{std::\libconcept{same_as}<decltype((*x)), typename T::inner>} is satisfied.

\begin{codeblock}
template<typename T> concept C3 =
  requires(T x) {
    {g(x)} noexcept;
  };
\end{codeblock}

The \grammarterm{compound-requirement} in \tcode{C3}
requires that \tcode{g(x)} is a valid expression and
that \tcode{g(x)} is non-throwing.
\end{example}

\rSec3[expr.prim.req.nested]{Nested requirements}
\indextext{requirement!nested}%

\begin{bnf}
\nontermdef{nested-requirement}\br
    \keyword{requires} constraint-expression \terminal{;}
\end{bnf}

\pnum
A \grammarterm{nested-requirement} can be used
to specify additional constraints in terms of local parameters.
The \grammarterm{constraint-expression}
shall be satisfied\iref{temp.constr.decl}
by the substituted template arguments, if any.
Substitution of template arguments into a \grammarterm{nested-requirement}
does not result in substitution into the \grammarterm{constraint-expression}
other than as specified in \ref{temp.constr.constr}.
\begin{example}
\begin{codeblock}
template<typename U> concept C = sizeof(U) == 1;

template<typename T> concept D = requires (T t) {
  requires C<decltype (+t)>;
};
\end{codeblock}
\tcode{D<T>} is satisfied if \tcode{sizeof(decltype (+t)) == 1}\iref{temp.constr.atomic}.
\end{example}
\indextext{expression!requires|)}
\indextext{expression!primary|)}

\rSec2[expr.prim.splice]{Expression splicing}

\begin{bnf}
\nontermdef{splice-expression}\br
    splice-specifier\br
    \keyword{template} splice-specifier\br
    \keyword{template} splice-specialization-specifier
\end{bnf}

\pnum
A \grammarterm{splice-specifier}
or \grammarterm{splice-specialization-specifier}
immediately followed by \tcode{::} or preceded by \keyword{typename}
is never interpreted as part of a \grammarterm{splice-expression}.
\begin{example}
\begin{codeblock}
struct S { static constexpr int a = 1; };
template<typename> struct TCls { static constexpr int b = 2; };

constexpr int c = [:^^S:]::a;                   // OK, \tcode{[:\caret\caret S:]} is not an expression
constexpr int d = template [:^^TCls:]<int>::b;  // OK, \tcode{template [:\caret\caret TCls:]<int>} is not an expression
template<auto V> constexpr int e = [:V:];       // OK
constexpr int f = template [:^^e:]<^^S::a>;     // OK

constexpr auto g = typename [:^^int:](42);      // OK, \tcode{typename [:\caret\caret int:]} is a \grammarterm{splice-type-specifier}

constexpr auto h = ^^g;
constexpr auto i = e<[:^^h:]>;          // error: unparenthesized \grammarterm{splice-expression} used as template argument
constexpr auto j = e<([:^^h:])>;        // OK
\end{codeblock}
\end{example}

\pnum
For a \grammarterm{splice-expression} $E$ of the form \grammarterm{splice-specifier},
let $S$ be the construct designated by \grammarterm{splice-specifier}.
\begin{itemize}
\item
The expression is ill-formed if $S$ is
\begin{itemize}
\item
a constructor,
\item
a destructor,
\item
an unnamed bit-field, or
\item
a local entity\iref{basic.pre} such that
\begin{itemize}
\item
there is a lambda scope that intervenes
between the expression and the point at which $S$ was introduced and
\item
the expression would be potentially evaluated
if the effect of any enclosing \keyword{typeid} expressions\iref{expr.typeid}
were ignored.
\end{itemize}
\end{itemize}
\item
Otherwise, if $S$ is a function $F$,
the expression denotes an overload set containing all declarations of $F$
that precede either the expression or
the point immediately following the \grammarterm{class-specifier} of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed\iref{over.match,over.over}.
\item
Otherwise, if $S$ is an object or a non-static data member,
the expression is an lvalue designating $S$.
The expression has the same type as that of $S$, and
is a bit-field if and only if $S$ is a bit-field.
\begin{note}
The implicit transformation
whereby an \grammarterm{id-expression} denoting a non-static member
becomes a class member access\iref{expr.prim.id}
does not apply to a \grammarterm{splice-expression}.
\end{note}
\item
Otherwise, if $S$ is a direct base class relationship $(\tcode{D}, \tcode{B})$,
the expression is an lvalue designating $S$.
The expression has the type \tcode{B}.
\item
Otherwise, if $S$ is a variable or a structured binding,
$S$ shall either have static or thread storage duration or
shall inhabit a scope enclosing the expression.
The expression $E$ is an lvalue referring to the object or function $X$
associated with or referenced by $S$, and
is a bit-field if and only if $X$ is a bit-field.
If $E$ appears in the predicate of a contract assertion $C$\iref{basic.contract}
and $S$ is
\begin{itemize}
\item
a variable declared outside of $C$
of object type \tcode{T},
\item
a variable declared outside of $C$
of type ``reference to \tcode{T}'', or
\item
a structured binding of type \tcode{T}
whose corresponding variable is declared outside of $C$,
\end{itemize}
then the type of $E$ is \tcode{const T},
otherwise $E$ has the same type as that of $S$.
\begin{note}
The type of a \grammarterm{splice-expression}
designating a variable or structured binding of reference type
will be adjusted to a non-reference type\iref{expr.type}.
\end{note}
\item
Otherwise, if $S$ is a value or an enumerator,
the expression is a prvalue that computes $S$ and
whose type is the same as that of $S$.
\item
Otherwise, the expression is ill-formed.
\end{itemize}

\pnum
For a \grammarterm{splice-expression} of
the form \tcode{\keyword{template} \grammarterm{splice-specifier}},
the \grammarterm{splice-specifier} shall designate a function template $T$
that is not a constructor template.
The expression denotes an overload set containing all declarations of $T$
that precede either the expression or
the point immediately following the \grammarterm{class-specifier} of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed.
\begin{note}
During overload resolution,
candidate function templates undergo template argument deduction and
the resulting specializations are considered as candidate functions.
\end{note}

\pnum
For a \grammarterm{splice-expression} of
the form \tcode{template \grammarterm{splice-specialization-specifier}},
the \grammarterm{splice-specifier} of
the \grammarterm{splice-specialization-specifier}
shall designate a template $T$.
\begin{itemize}
\item
If $T$ is a function template,
the expression denotes an overload set containing all declarations of $T$
that precede either the expression or
the point immediately following the \grammarterm{class-specifier} of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed\iref{over.match,over.over}.
\item
Otherwise, if $T$ is a variable template,
let $S$ be the specialization of $T$ corresponding to
the template argument list of the \grammarterm{splice-specialization-specifier}.
The expression is an lvalue referring to
the object associated with $S$ and has the same type as that of $S$.
\item
Otherwise, the expression is ill-formed.
\end{itemize}
\begin{note}
Class members are accessible from any point
when designated by \grammarterm{splice-expression}s\iref{class.access.base}.
A class member access expression\iref{expr.ref}
whose right operand is a \grammarterm{splice-expression} is ill-formed
if the left operand (considered as a pointer) cannot be implicitly converted
to a pointer to the designating class of the right operand.
\end{note}

\rSec1[expr.compound]{Compound expressions}

\rSec2[expr.post]{Postfix expressions}%

\rSec3[expr.post.general]{General}%
\indextext{expression!postfix|(}

\pnum
Postfix expressions group left-to-right.

\begin{bnf}
\nontermdef{postfix-expression}\br
    primary-expression\br
    postfix-expression \terminal{[} \opt{expression-list} \terminal{]}\br
    postfix-expression \terminal{(} \opt{expression-list} \terminal{)}\br
    simple-type-specifier \terminal{(} \opt{expression-list} \terminal{)}\br
    typename-specifier \terminal{(} \opt{expression-list} \terminal{)}\br
    simple-type-specifier braced-init-list\br
    typename-specifier braced-init-list\br
    postfix-expression \terminal{.} \opt{\keyword{template}} id-expression\br
    postfix-expression \terminal{.} splice-expression\br
    postfix-expression \terminal{->} \opt{\keyword{template}} id-expression\br
    postfix-expression \terminal{->} splice-expression\br
    postfix-expression \terminal{++}\br
    postfix-expression \terminal{--}\br
    \keyword{dynamic_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br
    \keyword{static_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br
    \keyword{reinterpret_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br
    \keyword{const_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br
    \keyword{typeid} \terminal{(} expression \terminal{)}\br
    \keyword{typeid} \terminal{(} type-id \terminal{)}
\end{bnf}

\begin{bnf}
\nontermdef{expression-list}\br
    initializer-list
\end{bnf}

\pnum
\begin{note}
The \tcode{>} token following the
\grammarterm{type-id} in a \keyword{dynamic_cast},
\keyword{static_cast}, \keyword{reinterpret_cast}, or
\keyword{const_cast} can be the product of replacing a
\tcode{>>} token by two consecutive \tcode{>}
tokens\iref{temp.names}.
\end{note}

\rSec3[expr.sub]{Subscripting}

\pnum
\indextext{operator!subscripting}%
\indextext{\idxcode{[]}|see{operator, subscripting}}%
A \defnadj{subscript}{expression} is a postfix expression
followed by square brackets containing
a possibly empty, comma-separated list of \grammarterm{initializer-clause}s
that constitute the arguments to the subscript operator.
The \grammarterm{postfix-expression} and
the initialization of the object parameter\iref{dcl.fct} of
any applicable subscript operator function\iref{over.sub} is sequenced before
each expression in the \grammarterm{expression-list} and also before
any default argument\iref{dcl.fct.default}.
The initialization of a non-object parameter of
a subscript operator function \tcode{S},
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of
any other non-object parameter of \tcode{S}.

\pnum
With the built-in subscript operator,
an \grammarterm{expression-list} shall be present,
consisting of a single \grammarterm{assignment-expression}.
One of the expressions shall be a glvalue of type ``array of
\tcode{T}'' or a prvalue of type ``pointer
to \tcode{T}'' and the other shall be a prvalue of unscoped enumeration or integral type.
The result is of type ``\tcode{T}''.
\indextext{type!incomplete}%
The type ``\tcode{T}'' shall be a completely-defined object type.%
\begin{footnote}
This
is true even if the subscript operator is used in the following common idiom:
\tcode{\&x[0]}.
\end{footnote}
The expression \tcode{E1[E2]} is identical (by definition) to
\tcode{*((E1)+(E2))},
except that in the case of an array operand, the result is an lvalue
if that operand is an lvalue and an xvalue otherwise.

\pnum
\begin{note}
Despite its asymmetric appearance, subscripting is a commutative
operation except for sequencing.
See~\ref{expr.unary} and~\ref{expr.add} for details of \tcode{*} and
\tcode{+} and~\ref{dcl.array} for details of array types.
\end{note}

\rSec3[expr.call]{Function call}

\pnum
\indextext{expression!function call}%
\indextext{operator!function call}%
\indextext{\idxcode{()}|see{operator, function call}}%
A function call is a postfix expression followed by parentheses
containing a possibly empty, comma-separated list of
\grammarterm{initializer-clause}{s} which
constitute the arguments to the function.
\begin{note}
If the postfix expression is a function name,
the appropriate function and the validity of the call
are determined according to the rules in~\ref{over.match}.
\end{note}
The postfix expression shall
have function type or function pointer type.
For a call to a non-member function or to a static member function,
the postfix expression shall be either an lvalue that refers to a
function (in which case the function-to-pointer standard
conversion\iref{conv.func} is suppressed on the postfix expression),
or a prvalue of function pointer type.

\pnum
If the selected
function is non-virtual, or if the \grammarterm{id-expression} in the class
member access expression is a \grammarterm{qualified-id}, that function is
called. Otherwise, its final overrider\iref{class.virtual} in the dynamic type
of the object expression is called; such a call is referred to as a
\defnx{virtual function call}{function!virtual function call}.
\begin{note}
The dynamic type is the type of the object referred to by the
current value of the object expression. \ref{class.cdtor}~describes the
behavior of virtual function calls when the object expression
refers to
an object under construction or destruction.
\end{note}

\pnum
\begin{note}
If a function name is used, and name
lookup\iref{basic.lookup} does not find a declaration of that name,
the program is ill-formed. No function is implicitly declared by such a
call.
\end{note}

\pnum
If the \grammarterm{postfix-expression} names
a destructor or pseudo-destructor\iref{expr.prim.id.dtor},
the type of the function call expression is \keyword{void}; otherwise, the
type of the function call expression is the return type of the
statically chosen function (i.e., ignoring the \keyword{virtual} keyword),
even if the type of the function actually called is different.
\indextext{type!incomplete}%
If the \grammarterm{postfix-expression} names a pseudo-destructor
(in which case the \grammarterm{postfix-expression}
is a possibly-parenthesized class member access),
the function call destroys
the object of scalar type
denoted by the object expression
of the class member access\iref{expr.ref,basic.life}.

\pnum
A type $\tcode{T}_\text{call}$ is
\defn{call-compatible} with a function type $\tcode{T}_\text{func}$
if $\tcode{T}_\text{call}$ is the same type as $\tcode{T}_\text{func}$ or
if the type ``pointer to $\tcode{T}_\text{func}$'' can be
converted to type ``pointer to $\tcode{T}_\text{call}$''
via a function pointer conversion\iref{conv.fctptr}.
Calling a function through an
expression whose function type
is not call-compatible with the
type of the called function's
definition results in undefined behavior.
\begin{note}
This requirement allows the case
when the expression has the type of a
potentially-throwing function, but the called function has
a non-throwing exception specification,
and the function types are otherwise the same.
\end{note}

\pnum
\indextext{function argument|see{argument}}%
\indextext{function parameter|see{parameter}}%
\indextext{initialization!parameter}%
When a function is called, each parameter\iref{dcl.fct} is
initialized\iref{dcl.init,class.copy.ctor} with
its corresponding argument,
and each precondition assertion of the function
is evaluated\iref{dcl.contract.func}.
If the function is an explicit object member function and
there is an implied object argument\iref{over.call.func},
the list of provided arguments is preceded by the implied object argument
for the purposes of this correspondence.
If there is no corresponding argument,
the default argument for the parameter is used.
\begin{example}
\begin{codeblock}
template<typename ...T> int f(int n = 0, T ...t);
int x = f<int>();               // error: no argument for second function parameter
\end{codeblock}
\end{example}
If the function is an implicit object member
function,
the object expression of the class member access shall be a glvalue and
the implicit object parameter of the function\iref{over.match.funcs}
is initialized with that glvalue,
converted as if by an explicit type conversion\iref{expr.cast}.
\begin{note}
There is no access or ambiguity checking on this conversion; the access
checking and disambiguation are done as part of the (possibly implicit)
class member access operator.
See~\ref{class.member.lookup}, \ref{class.access.base},
and~\ref{expr.ref}.
\end{note}
When a function is called, the type of any parameter
shall not be a class type that is either incomplete or abstract.
\begin{note}
This still allows a parameter to be a pointer or reference to such
a type. However, it prevents a passed-by-value parameter
to have an incomplete or abstract class type.
\end{note}
It is \impldef{whether a parameter is destroyed when the function
exits or at the end of the enclosing full-expression}
whether a parameter is destroyed
when the function in which it is defined exits\iref{stmt.return, except.ctor, expr.await}
or at the end of the enclosing full-expression;
parameters are always destroyed in the reverse order of their construction.
The initialization and destruction of each parameter occurs
within the context of the full-expression\iref{intro.execution}
where the function call appears.
\begin{example}
The access\iref{class.access.general} of the
constructor, conversion functions, or destructor is
checked at the point of call. If a constructor
or destructor for a function parameter throws an exception,
any \grammarterm{function-try-block}\iref{except.pre}
of the called function
with a handler that can handle the exception
is not considered.
\end{example}

\pnum
\indextext{evaluation!order of argument}%
\indextext{evaluation!unspecified order of function call}%
\indextext{evaluation!unspecified order of argument}%
The \grammarterm{postfix-expression} is sequenced before
each \grammarterm{expression} in the \grammarterm{expression-list}
and any default argument.
The initialization of a parameter or,
if the implementation introduces any temporary objects
to hold the values of function parameters\iref{class.temporary},
the initialization of those temporaries,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of any other parameter.
These evaluations are
sequenced before
the evaluation of the precondition assertions of the function,
which are evaluated in sequence\iref{dcl.contract.func}.
For any temporaries
introduced to hold the values of function parameters,
the initialization of the parameter objects from those temporaries
is indeterminately sequenced with respect to
the evaluation of each precondition assertion.
\begin{note}
All side effects of
argument evaluations are sequenced before the function is
entered (see~\ref{intro.execution}).
\end{note}
\begin{example}
\begin{codeblock}
void f() {
  std::string s = "but I have heard it works even if you don't believe in it";
  s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
  assert(s == "I have heard it works only if you believe in it");       // OK
}
\end{codeblock}
\end{example}
\begin{note}
If an operator function is invoked
using operator notation,
argument evaluation is sequenced
as specified for the built-in operator;
see~\ref{over.match.oper}.
\end{note}
\begin{example}
\begin{codeblock}
struct S {
  S(int);
};
int operator<<(S, int);
int i, j;
int x = S(i=1) << (i=2);
int y = operator<<(S(j=1), j=2);
\end{codeblock}
After performing the initializations,
the value of \tcode{i} is 2 (see~\ref{expr.shift}),
but it is unspecified whether the value of \tcode{j} is 1 or 2.
\end{example}

\pnum
The result of a function call is the result of the possibly-converted operand
of the \keyword{return} statement\iref{stmt.return}
that transferred control out of the called function (if any),
except in a virtual function call if the return type of the
final overrider is different from the return type of the statically
chosen function, the value returned from the final overrider is
converted to the return type of the statically chosen function.

\pnum
When the called function exits normally\iref{stmt.return,expr.await},
all postcondition assertions of the function
are evaluated in sequence\iref{dcl.contract.func}.
If the implementation introduces any temporary objects
to hold the result value as specified in \ref{class.temporary},
the evaluation of each postcondition assertion
is indeterminately sequenced with respect to
the initialization of any of those temporaries or the result object.
These evaluations, in turn, are sequenced before
the destruction of any function parameters.

\pnum
\begin{note}
\indextext{type checking!argument}%
\indextext{function call}%
\indextext{argument passing}%
\indextext{value!call by}%
\indextext{reference!call by}%
\indextext{argument!reference}%
A function can change the values of its non-const parameters, but these
changes cannot affect the values of the arguments except where a
parameter is of a reference type\iref{dcl.ref}; if the reference is to
a const-qualified type, \keyword{const_cast} needs to be used to
cast away the constness in order to modify the argument's value. Where a
parameter is of \keyword{const} reference type a temporary object is
introduced if
needed\iref{dcl.type,lex.literal,lex.string,dcl.array,class.temporary}.
In addition, it is possible to modify the values of non-constant objects through
pointer parameters.
\end{note}

\pnum
\indextext{declaration!ellipsis in function}%
\indextext{parameter list!variable}%
A function can be declared to accept fewer arguments (by declaring default
arguments\iref{dcl.fct.default}) or more arguments (by using the ellipsis,
\tcode{...}, or a function parameter pack\iref{dcl.fct}) than the number of
parameters in the function definition\iref{dcl.fct.def}.
\begin{note}
This implies that, except where the ellipsis (\tcode{...}) or a function
parameter pack is used, a parameter is available for each argument.
\end{note}

\pnum
\indextext{ellipsis!conversion sequence}%
When there is no parameter for a given argument, the argument is passed
in such a way that the receiving function can obtain the value of the
argument by invoking \libmacro{va_arg}\iref{support.runtime}.
\begin{note}
This paragraph does not apply to arguments passed to a function parameter pack.
Function parameter packs are expanded during template instantiation\iref{temp.variadic},
thus each such argument has a corresponding parameter when a function template
specialization is actually called.
\end{note}
The
lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array},
and function-to-pointer\iref{conv.func} standard conversions are
performed on the argument expression.
An argument that has type \cv{}~\tcode{std::nullptr_t} is converted
to type \tcode{\keyword{void}*}\iref{conv.ptr}.
After these conversions, if the
argument does not have arithmetic, enumeration, pointer, pointer-to-member,
or class type, the program is ill-formed.
Passing a potentially evaluated argument
of a scoped enumeration type\iref{dcl.enum} or
of a class type\iref{class} having
an eligible non-trivial copy constructor\iref{special,class.copy.ctor},
an eligible non-trivial move constructor, or
a non-trivial destructor\iref{class.dtor},
with no corresponding parameter, is conditionally-supported with
\impldef{passing argument of class type through ellipsis} semantics. If the argument has
integral or enumeration type that is subject to the integral
promotions\iref{conv.prom}, or a floating-point type that is subject to the
floating-point promotion\iref{conv.fpprom}, the value of the argument is converted to the
promoted type before the call. These promotions are referred to as
the \defnx{default argument promotions}{promotion!default argument promotion}.

\pnum
\indextext{function call!recursive}%
Recursive calls are permitted, except to the \tcode{main}
function\iref{basic.start.main}.

\pnum
A function call is an lvalue
if the result type is an lvalue reference type or an rvalue reference to function type,
an xvalue if the result type is an rvalue reference to object type, and a prvalue
otherwise.
If it is a non-void prvalue,
the type of the function call expression shall be complete,
except as specified in \ref{dcl.type.decltype}.

\rSec3[expr.type.conv]{Explicit type conversion (functional notation)}

\pnum
\indextext{expression!cast}%
\indextext{explicit type conversion|see{casting}}%
\indextext{type conversion, explicit|see{casting}}%
\indextext{conversion explicit type|see{casting}}%
\indextext{casting}%
A \grammarterm{simple-type-specifier}\iref{dcl.type.simple} or
\grammarterm{typename-specifier}\iref{temp.res} followed
by a parenthesized optional \grammarterm{expression-list} or
by a \grammarterm{braced-init-list}
(the initializer)
constructs a value of the specified type
given the initializer.
\indextext{deduction!class template arguments}%
If the type is a placeholder
for a deduced class type,
it is replaced by the return type
of the function selected by overload resolution
for class template deduction\iref{over.match.class.deduct}
for the remainder of this subclause.
Otherwise, if the type contains a placeholder type,
it is replaced by the type
determined by placeholder type deduction\iref{dcl.type.auto.deduct}.
Let \tcode{T} denote the resulting type.
Then:

\begin{itemize}
\item
If the initializer is a parenthesized single expression,
the type conversion expression is equivalent
to the corresponding cast
expression\iref{expr.cast}.

\item
\indextext{type!incomplete}%
Otherwise, if \tcode{T} is \cv{}~\keyword{void},
the initializer shall be \tcode{()} or \tcode{\{\}}
(after pack expansion, if any), and
the expression is a prvalue of type \keyword{void}
that performs no initialization.

\item
Otherwise, if \tcode{T} is a reference type,
the expression has the same effect as
direct-initializing an invented variable \tcode{t} of type \tcode{T} from
the initializer and then
using \tcode{t} as the result of the expression;
the result is an lvalue if
\tcode{T} is an lvalue reference type or
an rvalue reference to function type and
an xvalue otherwise.

\item
Otherwise,
the expression is a prvalue of type \tcode{T}
whose result object is direct-initialized\iref{dcl.init}
with the initializer.
\end{itemize}

If the initializer is a parenthesized optional \grammarterm{expression-list},
\tcode{T} shall not be an array type.
\begin{example}
\begin{codeblock}
struct A {};
void f(A&);             // \#1
void f(A&&);            // \#2
A& g();
void h() {
  f(g());               // calls \#1
  f(A(g()));            // calls \#2 with a temporary object
  f(auto(g()));         // calls \#2 with a temporary object
}
\end{codeblock}
\end{example}

\rSec3[expr.ref]{Class member access}

\pnum
\indextext{expression!class member access}%
\indextext{access control!class member}%
\indextext{syntax!class member}%
\indextext{semantics!class member}%
\indextext{operator!class member access}%
\indextext{\idxcode{.}|see{operator, class member access}}%
\indextext{dot operator|see{operator, class member access}}%
\indextext{operator!class member access}%
\indextext{\idxcode{->}|see{operator, class member access}}%
\indextext{arrow operator|see{operator, class member access}}%
A postfix expression followed by a dot \tcode{.} or an arrow \tcode{->},
optionally followed by the keyword
\keyword{template}, and then followed by an
\grammarterm{id-expression} or a \grammarterm{splice-expression},
is a postfix expression.
\begin{note}
If the keyword \keyword{template} is used and
followed by an \grammarterm{id-expression},
the unqualified name
is considered to refer to a template\iref{temp.names}.
If a \grammarterm{simple-template-id} results and is followed by a \tcode{::},
the \grammarterm{id-expression} is a \grammarterm{qualified-id}.
\end{note}

\pnum
\indextext{type!incomplete}%
For a dot that is followed by an expression
that designates a static member or an enumerator,
the first expression is a discarded-value expression\iref{expr.context};
if the expression after the dot designates a
non-static data member\iref{class.mem.general} or
a direct base class relationship\iref{class.derived.general},
the first expression shall be a glvalue.
A postfix expression that is followed by an arrow
shall be a prvalue having pointer type.
The expression \tcode{E1->E2} is
converted to the equivalent form \tcode{(*(E1)).E2}; the remainder of
\ref{expr.ref}~will address only the form using a dot.
\begin{footnote}
Note that
\tcode{(*(E1))} is an lvalue.
\end{footnote}

\pnum
The postfix expression before the dot is evaluated;
\begin{footnote}
If the class member
access expression is evaluated, the subexpression evaluation happens even if the
result is unnecessary to determine
the value of the entire postfix expression, for example if the
\grammarterm{id-expression} denotes a static member.
\end{footnote}
the result of that evaluation,
together with
the \grammarterm{id-expression} or \grammarterm{splice-expression},
determines the result of the entire postfix expression.

\pnum
Abbreviating
\grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} or
\grammarterm{postfix-expression}\tcode{.}\grammarterm{splice-expression}
as \tcode{E1.E2}, \tcode{E1} is called the \defn{object expression}.
If the object expression is of scalar type,
\tcode{E2} shall name the pseudo-destructor
of that same type (ignoring cv-qualifications) and
\tcode{E1.E2} is a prvalue of type ``function of () returning \keyword{void}''.
\begin{note}
This value can only be used
for a notional function call\iref{expr.prim.id.dtor}.
\end{note}

\pnum
Otherwise, the object expression shall be of class type.
The class type shall be complete
unless the class member access appears in the definition of that class.
\begin{note}
The program is ill-formed if the result differs from that
when the class is complete\iref{class.member.lookup}.
\end{note}
\begin{note}
\ref{basic.lookup.qual} describes how names are looked up after the
\tcode{.} and \tcode{->} operators.
\end{note}

\pnum
If \tcode{E2} is a \grammarterm{splice-expression},
then let \tcode{T1} be the type of \tcode{E1}.
\tcode{E2} shall designate either
a member of \tcode{T1} or
a direct base class relationship $(\tcode{T1}, \tcode{B})$.

\pnum
If \tcode{E2} designates a bit-field, \tcode{E1.E2} is a bit-field. The
type and value category of \tcode{E1.E2} are determined as follows.
In the remainder of~\ref{expr.ref}, \cvqual{cq} represents either
\keyword{const} or the absence of \keyword{const} and \cvqual{vq} represents
either \keyword{volatile} or the absence of \keyword{volatile}. \cvqual{cv}
represents an arbitrary set of cv-qualifiers, as defined
in~\ref{basic.type.qualifier}.

\pnum
If \tcode{E2} designates an entity
that is declared to have type ``reference to \tcode{T}'', then
\tcode{E1.E2} is an lvalue of type \tcode{T}.
In that case, if \tcode{E2} designates a static data member,
\tcode{E1.E2} designates the object or function to which
the reference is bound,
otherwise \tcode{E1.E2} designates the object or function to which
the corresponding reference member of \tcode{E1} is bound.
Otherwise, one of the following rules applies.
\begin{itemize}
\item
If \tcode{E2} designates a static data member and the type of \tcode{E2}
is \tcode{T}, then \tcode{E1.E2} is an lvalue; the expression designates
the named member of the class. The type of \tcode{E1.E2} is \tcode{T}.

\item
Otherwise, if \tcode{E2} designates a non-static data member and the type of
\tcode{E1} is ``\cvqual{cq1 vq1} \tcode{X}'', and the type of \tcode{E2}
is ``\cvqual{cq2 vq2} \tcode{T}'', the expression designates the corresponding
member subobject of the object designated by \tcode{E1}. If \tcode{E1}
is an lvalue, then \tcode{E1.E2} is an lvalue;
otherwise \tcode{E1.E2} is an xvalue.
Let the notation \cvqual{vq12} stand for the ``union'' of
\cvqual{vq1} and \cvqual{vq2}; that is, if \cvqual{vq1} or \cvqual{vq2}
is \tcode{volatile}, then \cvqual{vq12} is \keyword{volatile}. Similarly,
let the notation \cvqual{cq12} stand for the ``union'' of \cvqual{cq1}
and \cvqual{cq2}; that is, if \cvqual{cq1} or \cvqual{cq2} is
\keyword{const}, then \cvqual{cq12} is \keyword{const}.
If the entity designated by \tcode{E2}
is declared to be a \keyword{mutable} member,
then the type of \tcode{E1.E2} is ``\cvqual{vq12} \tcode{T}''.
If the entity designated by \tcode{E2}
is not declared to be a \keyword{mutable} member,
then the type of \tcode{E1.E2} is ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''.

\item
Otherwise, if \tcode{E2} denotes an overload set,
the expression shall be the (possibly-parenthesized) left-hand operand of
a member function call\iref{expr.call}, and
function overload resolution\iref{over.match}
is used to select the function to which \tcode{E2} refers.
The type of \tcode{E1.E2} is the type of \tcode{E2}
and \tcode{E1.E2} refers to the function referred to by \tcode{E2}.
\begin{itemize}
\item
If \tcode{E2} refers to a static member function,
\tcode{E1.E2} is an lvalue.
\item
Otherwise (when \tcode{E2} refers to a non-static member function),
\tcode{E1.E2} is a prvalue.
\begin{note}
Any redundant set of parentheses surrounding the expression
is ignored\iref{expr.prim.paren}.
\end{note}
\end{itemize}

\item
Otherwise, if \tcode{E2} designates a nested type,
the expression \tcode{E1.E2} is ill-formed.

\item
Otherwise, if \tcode{E2} designates a member enumerator and the type of \tcode{E2}
is \tcode{T}, the expression \tcode{E1.E2} is a prvalue of type \tcode{T}
whose value is the value of the enumerator.

\item
Otherwise, if \tcode{E2} designates a direct base class relationship $(D, B)$ and
$D$ is either the cv-unqualified class type of \tcode{E1} or a base class thereof,
let \cv{} be the cv-qualification of the type of \tcode{E1}.
\tcode{E1} is implicitly converted to the type ``reference to \cv{}~\tcode{$D$}''
(where the reference is an lvalue reference if \tcode{E1} is an lvalue
and an rvalue reference otherwise) and
the expression designates the direct base class subobject of type $B$
of the object designated by the converted \tcode{E1}.
If \tcode{E1} is an lvalue,
then \tcode{E1.E2} is an lvalue;
otherwise, \tcode{E1.E2} is an xvalue.
The type of \tcode{E1.E2} is \cv{}~\tcode{$B$}.
\begin{example}
\begin{codeblock}
struct B {
  int b;
};
struct C : B {
  int get() const { return b; }
};
struct D : B, C { };

constexpr int f() {
  D d = {1, {}};

  // \tcode{b} unambiguously refers to the direct base class of type \tcode{B},
  // not the indirect base class of type \tcode{B}
  B& b = d.[: std::meta::bases_of(^^D, std::meta::access_context::current())[0] :];
  b.b += 10;
  return 10 * b.b + d.get();
}
static_assert(f() == 110);
\end{codeblock}
\end{example}

\item
Otherwise, the program is ill-formed.
\end{itemize}

\pnum
If \tcode{E2} designates a non-static member
(possibly after overload resolution),
the program is ill-formed if the class of which \tcode{E2} designates
a direct member is an ambiguous base\iref{class.member.lookup} of
the designating class\iref{class.access.base} of \tcode{E2}.
\begin{note}
The program is also ill-formed if the naming class is an ambiguous base of the class type
of the object expression; see~\ref{class.access.base}.
\end{note}

\pnum
If \tcode{E2} designates a non-static member
(possibly after overload resolution)
or direct base class relationship and
the result of \tcode{E1} is an object whose type
is not similar\iref{conv.qual} to the type of \tcode{E1},
the behavior is undefined.
\begin{example}
\begin{codeblock}
struct A { int i; };
struct B { int j; };
struct D : A, B {};
void f() {
  D d;
  static_cast<B&>(d).j;             // OK, object expression designates the \tcode{B} subobject of \tcode{d}
  reinterpret_cast<B&>(d).j;        // undefined behavior
}
\end{codeblock}
\end{example}

\rSec3[expr.post.incr]{Increment and decrement}

\pnum
\indextext{expression!increment}%
\indextext{operator!increment}%
\indextext{\idxcode{++}|see{operator, increment}}%
\indextext{postfix \tcode{++}}%
The value of a postfix \tcode{++} expression is the value obtained by
applying the lvalue-to-rvalue conversion\iref{conv.lval} to its operand.
\begin{note}
The value obtained is a copy of the original value.
\end{note}
The operand shall be a modifiable lvalue. The type of the operand shall
be an arithmetic type other than \cv{}~\keyword{bool},
or a pointer to a complete object type.
An operand with volatile-qualified type is deprecated;
see~\ref{depr.volatile.type}.
The value of the operand object is modified\iref{defns.access}
as if it were the operand of the prefix \tcode{++} operator\iref{expr.pre.incr}.
The
\indextext{value computation}%
value computation of the \tcode{++} expression is sequenced before the
modification of the operand object. With respect to an
indeterminately-sequenced function call, the operation of postfix
\tcode{++} is
a single evaluation.
\begin{note}
Therefore, a function call cannot intervene between the
lvalue-to-rvalue conversion and the side effect associated with any
single postfix \tcode{++} operator.
\end{note}
The result is a prvalue. The type of the result is the cv-unqualified
version of the type of the operand.

\pnum
\indextext{expression!decrement}%
\indextext{operator!decrement}%
\indextext{\idxcode{--}|see{operator, decrement}}%
\indextext{postfix \tcode{--}}%
The operand of postfix \tcode{--} is decremented analogously to the
postfix \tcode{++} operator.
\begin{note}
For prefix increment and decrement, see~\ref{expr.pre.incr}.
\end{note}

\rSec3[expr.dynamic.cast]{Dynamic cast}

\pnum
\indextext{expression!dynamic cast}%
\indextext{cast!dynamic}%
The result of the expression \tcode{\keyword{dynamic_cast}<T>(v)} is the result of
converting the expression \tcode{v} to type \tcode{T}.
\indextext{type!incomplete}%
\tcode{T} shall be a pointer or reference to a complete class type, or
``pointer to \cv{} \keyword{void}''. The \keyword{dynamic_cast} operator shall not cast
away constness\iref{expr.const.cast}.

\pnum
If \tcode{T} is a pointer type, \tcode{v} shall be a prvalue of a
pointer to complete class type, and the result is a prvalue of type
\tcode{T}. If \tcode{T} is an lvalue reference type, \tcode{v} shall be
an lvalue of a complete class type, and the result is an lvalue of the
type referred to by \tcode{T}. If \tcode{T} is an rvalue reference type,
\tcode{v} shall be a glvalue having a complete class type, and the
result is an xvalue of the type referred to by \tcode{T}.

\pnum
If the type of \tcode{v} is the same as \tcode{T} (ignoring cv-qualifications),
the result is
\tcode{v} (converted if necessary).

\pnum
If \tcode{T} is ``pointer to \cvqual{cv1} \tcode{B}'' and \tcode{v} has
type ``pointer to \cvqual{cv2} \tcode{D}'' such that \tcode{B} is a base
class of \tcode{D}, the result is a pointer to the unique \tcode{B}
subobject of the \tcode{D} object pointed to by \tcode{v}, or
a null pointer value if \tcode{v} is a null pointer value.
Similarly, if
\tcode{T} is ``reference to \cvqual{cv1} \tcode{B}'' and \tcode{v} has
type \cvqual{cv2} \tcode{D} such that \tcode{B} is a base class of
\tcode{D}, the result is the unique \tcode{B} subobject of the \tcode{D}
object referred to by \tcode{v}.
\begin{footnote}
The most derived
object\iref{intro.object} pointed or referred to by
\tcode{v} can contain other \tcode{B} objects as base classes, but these
are ignored.
\end{footnote}
In both the pointer and
reference cases, the program is ill-formed if \tcode{B} is an inaccessible or
ambiguous base class of \tcode{D}.
\begin{example}
\begin{codeblock}
struct B { };
struct D : B { };
void foo(D* dp) {
  B*  bp = dynamic_cast<B*>(dp);    // equivalent to \tcode{B* bp = dp;}
}
\end{codeblock}
\end{example}

\pnum
Otherwise, \tcode{v} shall be a pointer to or a glvalue of a polymorphic
type\iref{class.virtual}.

\pnum
If \tcode{v} is a null pointer value, the result is a null pointer value.

\pnum
If \tcode{v} has type ``pointer to \cv{}~\tcode{U}'' and
\tcode{v} does not point to an object
whose type is similar\iref{conv.qual} to \tcode{U} and
that is
within its lifetime or
within its period of construction or destruction\iref{class.cdtor},
the behavior is undefined.
If \tcode{v} is a glvalue of type \tcode{U} and
\tcode{v} does not refer to an object
whose type is similar to \tcode{U} and
that is
within its lifetime or
within its period of construction or destruction,
the behavior is undefined.

\pnum
If \tcode{T} is ``pointer to \cv{} \keyword{void}'', then the result
is a pointer to the most derived object pointed to by \tcode{v}.
Otherwise, a runtime check is applied to see if the object pointed or
referred to by \tcode{v} can be converted to the type pointed or
referred to by \tcode{T}.

\pnum
Let \tcode{C} be the class type to which \tcode{T} points or refers. The runtime
check logically executes as follows:

\begin{itemize}
\item If, in the most derived object pointed (referred) to by \tcode{v},
\tcode{v} points (refers) to a public base class subobject of a
\tcode{C} object, and if only one object of type \tcode{C} is derived
from the subobject pointed (referred) to by \tcode{v},
the result points (refers) to that \tcode{C} object.

\item Otherwise, if \tcode{v} points (refers) to a public base
class subobject of the most derived object, and the type of the most
derived object has a base class, of type \tcode{C}, that is unambiguous
and public, the result points (refers) to the
\tcode{C} subobject of the most derived object.

\item Otherwise, the
runtime check \term{fails}.
\end{itemize}

\pnum
The value of a failed cast to pointer type is the null pointer value of
the required result type. A failed cast to reference type throws
an exception\iref{except.throw} of a type that would match a
handler\iref{except.handle} of type \tcode{std::bad_cast}\iref{bad.cast}.

\indextext{\idxcode{bad_cast}}%
\indexlibraryglobal{bad_cast}%
\begin{example}
\begin{codeblock}
class A { virtual void f(); };
class B { virtual void g(); };
class D : public virtual A, private B { };
void g() {
  D   d;
  B*  bp = (B*)&d;                  // cast needed to break protection
  A*  ap = &d;                      // public derivation, no cast needed
  D&  dr = dynamic_cast<D&>(*bp);   // fails
  ap = dynamic_cast<A*>(bp);        // fails
  bp = dynamic_cast<B*>(ap);        // fails
  ap = dynamic_cast<A*>(&d);        // succeeds
  bp = dynamic_cast<B*>(&d);        // ill-formed (not a runtime check)
}

class E : public D, public B { };
class F : public E, public D { };
void h() {
  F   f;
  A*  ap  = &f;                     // succeeds: finds unique \tcode{A}
  D*  dp  = dynamic_cast<D*>(ap);   // fails: yields null; \tcode{f} has two \tcode{D} subobjects
  E*  ep  = (E*)ap;                 // error: cast from virtual base
  E*  ep1 = dynamic_cast<E*>(ap);   // succeeds
}
\end{codeblock}
\end{example}
\begin{note}
Subclause \ref{class.cdtor} describes the behavior of a \keyword{dynamic_cast}
applied to an object under construction or destruction.
\end{note}

\rSec3[expr.typeid]{Type identification}

\pnum
\indextext{expression!type identification}%
\indextext{\idxcode{typeid}}%
The result of a \keyword{typeid} expression is an lvalue of static type
\indextext{\idxcode{type_info}}%
\indexlibraryglobal{type_info}%
\keyword{const} \tcode{std::type_info}\iref{type.info} and dynamic type \keyword{const}
\tcode{std::type_info} or \keyword{const} \tcode{\placeholder{name}} where \tcode{\placeholder{name}} is an
\impldef{derived type for \tcode{typeid}} class publicly derived from
\tcode{std::type_info} which preserves the behavior described
in~\ref{type.info}.
\begin{footnote}
The recommended name for such a class is
\tcode{extended_type_info}.
\end{footnote}
The lifetime of the object referred to by the lvalue extends to the end
of the program. Whether or not the destructor is called for the
\tcode{std::type_info} object at the end of the program is unspecified.

\pnum
If the type of the \grammarterm{expression} or \grammarterm{type-id} operand is
a (possibly cv-qualified) class type or
a reference to (possibly cv-qualified) class type,
that class shall be completely defined.

\pnum
If an \grammarterm{expression} operand of \keyword{typeid} is
a possibly-parenthesized \grammarterm{unary-expression}
whose \grammarterm{unary-operator} is \tcode{*} and
whose operand evaluates to a null pointer value\iref{basic.compound},
the \keyword{typeid} expression throws an exception\iref{except.throw}
of a type that would match a handler of type
\indextext{\idxcode{bad_typeid}}%
\indexlibraryglobal{bad_typeid}%
\tcode{std::bad_typeid}\iref{bad.typeid}.
\begin{note}
In other contexts, evaluating such a \grammarterm{unary-expression}
results in undefined behavior\iref{expr.unary.op}.
\end{note}

\pnum
When \keyword{typeid} is applied to a glvalue whose type is a
polymorphic class type\iref{class.virtual}, the result refers to a
\tcode{std::type_info} object representing the type of the most derived
object\iref{intro.object} (that is, the dynamic type) to which the
glvalue refers.

\pnum
When \keyword{typeid} is applied to an expression other than a glvalue of
a polymorphic class type, the result refers to a \tcode{std::type_info}
object representing the static type of the expression.
Lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array},
and function-to-pointer\iref{conv.func} conversions are not applied to
the expression.
If the expression is a prvalue,
the temporary materialization conversion\iref{conv.rval}
is applied.
The expression is an unevaluated operand\iref{term.unevaluated.operand}.

\pnum
When \keyword{typeid} is applied to a \grammarterm{type-id}, the result
refers to a \tcode{std::type_info} object representing the type of the
\grammarterm{type-id}. If the type of the \grammarterm{type-id} is a reference
to a possibly cv-qualified type, the result of the
\keyword{typeid} expression refers to a \tcode{std::type_info} object
representing the cv-unqualified referenced type.
\begin{note}
The \grammarterm{type-id} cannot denote a function type with
a \grammarterm{cv-qualifier-seq} or a \grammarterm{ref-qualifier}\iref{dcl.fct}.
\end{note}

\pnum
If the type of the expression or \grammarterm{type-id} is a
cv-qualified type, the result of the \keyword{typeid} expression refers
to a \tcode{std::type_info} object representing the cv-unqualified
type.
\begin{example}
\begin{codeblock}
class D { @\commentellip@ };
D d1;
const D d2;

typeid(d1) == typeid(d2);       // yields \tcode{true}
typeid(D)  == typeid(const D);  // yields \tcode{true}
typeid(D)  == typeid(d2);       // yields \tcode{true}
typeid(D)  == typeid(const D&); // yields \tcode{true}
\end{codeblock}
\end{example}

\pnum
The type \tcode{std::type_info}\iref{type.info} is not predefined;
if a standard library declaration\iref{typeinfo.syn,std.modules} of
\tcode{std::type_info} does not precede\iref{basic.lookup.general}
a \tcode{typeid} expression, the program is ill-formed.

\pnum
\begin{note}
Subclause \ref{class.cdtor} describes the behavior of \keyword{typeid}
applied to an object under construction or destruction.
\end{note}

\rSec3[expr.static.cast]{Static cast}

\pnum
\indextext{expression!static cast}%
\indextext{cast!static}%
The result of the expression \tcode{\keyword{static_cast}<T>(v)} is the result of
converting the expression \tcode{v} to type \tcode{T}.
\indextext{cast!static!lvalue}%
\indextext{cast!lvalue}%
If \tcode{T} is an lvalue reference type
or an rvalue reference to function type, the result is an lvalue;
if \tcode{T} is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue.

\pnum
\indextext{cast!static!reference}%
\indextext{cast!reference}%
An lvalue of type ``\cvqual{cv1} \tcode{B}'', where \tcode{B} is a class
type, can be cast to type ``reference to \cvqual{cv2} \tcode{D}'', where
\tcode{D} is a complete class derived\iref{class.derived} from \tcode{B},
if \cvqual{cv2} is the
same cv-qualification as, or greater cv-qualification than,
\cvqual{cv1}. If \tcode{B} is a virtual base class of \tcode{D}
or a base class of a virtual base class of \tcode{D},
or if no valid standard conversion from ``pointer to \tcode{D}''
to ``pointer to \tcode{B}'' exists\iref{conv.ptr}, the program is ill-formed.
An xvalue of type
``\cvqual{cv1} \tcode{B}'' can be cast to type ``rvalue reference to
\cvqual{cv2} \tcode{D}'' with the same constraints as for an lvalue of
type ``\cvqual{cv1} \tcode{B}''. If the object
of type ``\cvqual{cv1} \tcode{B}'' is actually a base class subobject of an object
of type \tcode{D}, the result refers to the enclosing object of type
\tcode{D}. Otherwise, the behavior is undefined.
\begin{example}
\begin{codeblock}
struct B { };
struct D : public B { };
D d;
B &br = d;

static_cast<D&>(br);            // produces lvalue denoting the original \tcode{d} object
\end{codeblock}
\end{example}

\pnum
An lvalue
of type \tcode{T1} can be cast to type ``rvalue
reference to \tcode{T2}'' if \tcode{T2} is reference-compatible with
\tcode{T1}\iref{dcl.init.ref}. If the value is not a bit-field,
the result refers to the object or the specified base class subobject
thereof; otherwise, the lvalue-to-rvalue conversion\iref{conv.lval}
is applied to the bit-field and the resulting prvalue is used as the
operand of the \keyword{static_cast} for the remainder of this subclause.
If \tcode{T2} is an inaccessible\iref{class.access} or
ambiguous\iref{class.member.lookup} base class of \tcode{T1},
a program that necessitates such a cast is ill-formed.

\pnum
Any expression can be explicitly converted to type \cv{}~\keyword{void},
in which case the operand is a discarded-value expression\iref{expr.prop}.
\begin{note}
Such a \keyword{static_cast} has no result
as it is a prvalue of type \keyword{void}; see~\ref{basic.lval}.
\end{note}
\begin{note}
However, if the value is in a temporary
object\iref{class.temporary}, the destructor for that
object is
not executed until the usual time, and the value of the object is
preserved for the purpose of executing the destructor.
\end{note}

\pnum
Otherwise, an expression $E$ can be explicitly converted to a type \tcode{T}
if there is an implicit conversion sequence\iref{over.best.ics}
from $E$ to \tcode{T},
if overload resolution for a direct-initialization\iref{dcl.init}
of an object or reference of type \tcode{T} from $E$
would find at least one viable function\iref{over.match.viable}, or
if \tcode{T} is an aggregate type\iref{dcl.init.aggr}
having a first element \tcode{x} and
there is an implicit conversion sequence
from $E$ to the type of \tcode{x}.
If \tcode{T} is a reference type, the effect is
the same as performing the declaration and initialization
\begin{codeblock}
T t(@$E$@);
\end{codeblock}
for some invented temporary variable \tcode{t}\iref{dcl.init}
and then using the temporary variable as the result of the conversion.
Otherwise, the result object is direct-initialized from $E$.
\begin{note}
The conversion is ill-formed when attempting to convert an
expression of class type to an inaccessible or ambiguous base class.
\end{note}
\begin{note}
If \tcode{T} is ``array of unknown bound of \tcode{U}'',
this direct-initialization defines the type of the expression as \tcode{U[1]}.
\end{note}

\pnum
Otherwise, the lvalue-to-rvalue\iref{conv.lval},
array-to-pointer\iref{conv.array}, and
function-to-pointer\iref{conv.func} conversions are applied to the
operand, and the conversions that can be performed using \keyword{static_cast} are listed below.
No other conversion can be performed using \keyword{static_cast}.

\pnum
A value of a scoped enumeration type\iref{dcl.enum}
can be explicitly converted to an integral type;
the result is the same as that of converting
to the enumeration's underlying type and then to the destination type.
A value of a scoped enumeration type
can also be explicitly converted to a floating-point type;
the result is the same as that of converting
from the original value to the floating-point type.

\pnum
\indextext{enumeration type!conversion to}%
\indextext{enumeration type!\idxcode{static_cast}!conversion to}%
A value of integral or enumeration type can be explicitly converted to
a complete enumeration type.
If the enumeration type has a fixed underlying type,
the value is first converted to that type
by
integral promotion\iref{conv.prom} or integral conversion\iref{conv.integral},
if necessary, and
then to the enumeration type.
If the enumeration type does not have a fixed underlying type,
the value is unchanged
if the original value is within the range
of the enumeration values\iref{dcl.enum}, and
otherwise, the behavior is undefined.
A value of floating-point type can also be explicitly converted to an enumeration type.
The resulting value is the same as converting the original value to the
underlying type of the enumeration\iref{conv.fpint}, and subsequently to
the enumeration type.

\pnum
A prvalue of floating-point type can be explicitly converted to
any other floating-point type.
If the source value can be exactly represented in the destination type,
the result of the conversion has that exact representation.
If the source value is between two adjacent destination values,
the result of the conversion is
an \impldef{result of inexact floating-point conversion} choice of
either of those values.
Otherwise, the behavior is undefined.

\pnum
\indextext{cast!base class}%
\indextext{cast!derived class}%
A prvalue of type ``pointer to \cvqual{cv1} \tcode{B}'', where \tcode{B}
is a class type, can be converted to a prvalue of type ``pointer to
\cvqual{cv2} \tcode{D}'',
where \tcode{D} is a complete class derived\iref{class.derived}
from \tcode{B},
if \cvqual{cv2} is the same cv-qualification as,
or greater cv-qualification than, \cvqual{cv1}.
If \tcode{B} is a virtual base class of \tcode{D} or
a base class of a virtual base class of \tcode{D}, or
if no valid standard conversion from ``pointer to \tcode{D}''
to ``pointer to \tcode{B}'' exists\iref{conv.ptr}, the program is ill-formed.
The null pointer value\iref{basic.compound} is converted
to the null pointer value of the destination type. If the prvalue of type
``pointer to \cvqual{cv1} \tcode{B}'' points to a \tcode{B} that is
actually a base class subobject of an object of type \tcode{D}, the resulting
pointer points to the enclosing object of type \tcode{D}. Otherwise, the
behavior is undefined.

\pnum
\indextext{cast!pointer-to-member}%
A prvalue of type ``pointer to member of \tcode{D} of type \cvqual{cv1}
\tcode{T}'' can be converted to a prvalue of type ``pointer to member of
\tcode{B} of type \cvqual{cv2} \tcode{T}'', where
\tcode{D} is a complete class type and
\tcode{B} is a base class\iref{class.derived} of \tcode{D},
if \cvqual{cv2} is the same cv-qualification
as, or greater cv-qualification than, \cvqual{cv1}.
\begin{note}
Function types (including those used in pointer-to-member-function types)
are never cv-qualified\iref{dcl.fct}.
\end{note}
If no valid standard conversion
from ``pointer to member of \tcode{B} of type \tcode{T}''
to ``pointer to member of \tcode{D} of type \tcode{T}''
exists\iref{conv.mem}, the program is ill-formed.
The null member pointer value\iref{conv.mem} is converted to the null
member pointer value of the destination type. If class \tcode{B}
contains the original member, or is a base class of the class
containing the original member, the resulting pointer to member points
to the original member. Otherwise, the behavior is undefined.
\begin{note}
Although class \tcode{B} need not contain the original member, the
dynamic type of the object with which indirection through the pointer
to member is performed must contain the original member;
see~\ref{expr.mptr.oper}.
\end{note}

\pnum
A prvalue of type ``pointer to \cvqual{cv1} \keyword{void}'' can be
converted to a prvalue of type ``pointer to \cvqual{cv2} \tcode{T}'',
where \tcode{T} is an object type and \cvqual{cv2} is the same
cv-qualification as, or greater cv-qualification than, \cvqual{cv1}.
If the original pointer value represents the address
\tcode{A} of a byte in memory and
\tcode{A} does not satisfy the alignment requirement of \tcode{T},
then the resulting pointer value\iref{basic.compound} is unspecified.
Otherwise, if the original pointer value points to an object \placeholder{a},
and there is an object \placeholder{b} of type similar to \tcode{T}
that is pointer-interconvertible\iref{basic.compound} with \placeholder{a},
the result is a pointer to \placeholder{b}.
Otherwise, the pointer value is unchanged by the conversion.
\begin{example}
\begin{codeblock}
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
bool b = p1 == p2;  // \tcode{b} will have the value \tcode{true}.
\end{codeblock}
\end{example}

\rSec3[expr.reinterpret.cast]{Reinterpret cast}

\pnum
\indextext{expression!reinterpret cast}%
\indextext{cast!reinterpret}%
The result of the expression \tcode{\keyword{reinterpret_cast}<T>(v)} is the
result of converting the expression \tcode{v} to type \tcode{T}.
\indextext{cast!reinterpret!lvalue}%
\indextext{cast!lvalue}%
If \tcode{T} is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
if \tcode{T} is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the
lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array},
and function-to-pointer\iref{conv.func} standard conversions are
performed on the expression \tcode{v}. Conversions that can be performed explicitly
using \keyword{reinterpret_cast} are listed below. No other conversion can
be performed explicitly using \keyword{reinterpret_cast}.

\pnum
The \keyword{reinterpret_cast} operator shall not cast away constness\iref{expr.const.cast}.
An expression of integral, enumeration, pointer, or pointer-to-member type
can be explicitly converted to its own type; such a cast yields the value of
its operand.

\pnum
\begin{note}
The mapping performed by \keyword{reinterpret_cast} might, or might not, produce a
representation different from the original value.
\end{note}

\pnum
\indextext{cast!reinterpret!pointer to integer}%
\indextext{cast!pointer to integer}%
A pointer can be explicitly converted to any integral type large enough
to hold all values of its type.
\indextext{conversion!implementation-defined pointer integer}%
The mapping function is \impldef{mapping of pointer to integer}.
\begin{note}
It is intended to be unsurprising to those who know the addressing
structure of the underlying machine.
\end{note}
A value of type \tcode{std::nullptr_t} can be converted to an integral
type; the conversion has the same meaning and validity as a conversion of
\tcode{(\keyword{void}*)0} to the integral type.
\begin{note}
A \keyword{reinterpret_cast}
cannot be used to convert a value of any type to the type
\tcode{std::nullptr_t}.
\end{note}

\pnum
\indextext{cast!reinterpret!integer to pointer}%
\indextext{cast!integer to pointer}%
A value of integral type or enumeration type can be explicitly converted
to a pointer. A pointer converted to an integer of sufficient size (if
any such exists on the implementation) and back to the same pointer type
will have its original value\iref{basic.compound};
\indextext{conversion!implementation-defined pointer integer}%
mappings between pointers and integers are otherwise
\impldef{conversions between pointers and integers}.

\pnum
\indextext{cast!reinterpret!pointer-to-function}%
\indextext{cast!pointer-to-function}%
\indextext{cast!undefined pointer-to-function}%
A function pointer can be explicitly converted
to a function pointer of a different type.
The function pointer value is unchanged by the conversion.
\indextext{function call!undefined}%
\begin{note}
The effect of calling a function through a pointer to a function
type\iref{dcl.fct} that is not call-compatible with the type used in the
definition of the function is undefined\iref{expr.call}.
\end{note}

\pnum
An object pointer
can be explicitly converted to an object pointer of a different type.
\begin{footnote}
The
types can have different \cv-qualifiers, subject to
the overall
restriction that a \keyword{reinterpret_cast} cannot cast away constness.
\end{footnote}
When a prvalue \tcode{v} of object pointer type is converted to
the object pointer type ``pointer to \cv{}~\tcode{T}'', the result is \tcode{\keyword{static_cast}<\cv{} T*>(\keyword{static_cast}<\cv{}~\keyword{void}*>(v))}.
\begin{note}
Converting a pointer of type ``pointer to \tcode{T1}''
that points to an object of type \tcode{T1}
to the type ``pointer to \tcode{T2}''
(where \tcode{T2} is an object type
and the alignment requirements of \tcode{T2}
are no stricter than those of \tcode{T1})
and back to its original type yields the original pointer value.
\end{note}

\pnum
Converting a function pointer to an object pointer
type or vice versa is
conditionally-supported. The meaning of such a conversion is
\impldef{converting function pointer to object pointer and vice versa},
except that if an implementation
supports conversions in both directions, converting a prvalue of one type to the other
type and back, possibly with different cv-qualification, shall yield the original
pointer value.

\pnum
The null pointer value\iref{basic.compound} is converted to the null pointer value
of the destination type.
\begin{note}
A null pointer constant of type \tcode{std::nullptr_t} cannot be converted to a
pointer type, and a null pointer constant of integral type is not necessarily
converted to a null pointer value.
\end{note}

\pnum
\indextext{cast!reinterpret!pointer-to-member}%
\indextext{cast!pointer-to-member}%
A prvalue of type ``pointer to member of \tcode{X} of type \tcode{T1}''
can be explicitly converted to a prvalue of a different type ``pointer to member of
\tcode{Y} of type \tcode{T2}'' if \tcode{T1} and \tcode{T2} are both
function types or both object types.
\begin{footnote}
\tcode{T1} and \tcode{T2} can have
different \cv-qualifiers, subject to
the overall restriction that a \keyword{reinterpret_cast} cannot cast away
constness.
\end{footnote}
The null member pointer value\iref{conv.mem} is converted to the
null member pointer value of the destination type. The result of this
conversion is unspecified, except in the following cases:

\begin{itemize}
\item Converting a prvalue of type ``pointer to member function'' to a
different pointer-to-member-function type and back to its original type
yields the original pointer-to-member value.

\item Converting a prvalue of type ``pointer to data member of \tcode{X}
of type \tcode{T1}'' to the type ``pointer to data member of \tcode{Y}
of type \tcode{T2}'' (where the alignment requirements of \tcode{T2} are
no stricter than those of \tcode{T1}) and back to its original type
yields the original pointer-to-member value.
\end{itemize}

\pnum
\indextext{cast!reinterpret!reference}%
\indextext{cast!reference}%
\indextext{type pun}%
If \tcode{v} is a glvalue of type \tcode{T1},
designating an object or function \placeholder{x},
it can be cast to the type ``reference to \tcode{T2}''
if an expression of type ``pointer to \tcode{T1}''
can be explicitly converted to the type ``pointer to \tcode{T2}''
using a \keyword{reinterpret_cast}.
The result is that of \tcode{*reinterpret_cast<T2 *>(p)}
where \tcode{p} is a pointer to \placeholder{x}
of type ``pointer to \tcode{T1}''.
\begin{note}
No temporary is materialized\iref{conv.rval} or created,
no copy is made, and
no constructors\iref{class.ctor} or conversion
functions\iref{class.conv} are called.
\begin{footnote}
This is sometimes referred to as a type pun
when the result refers to the same object as the source glvalue.
\end{footnote}
\end{note}

\rSec3[expr.const.cast]{Const cast}

\pnum
\indextext{expression!const cast}%
\indextext{cast!const}%
The result of the expression \tcode{\keyword{const_cast}<T>(v)} is of type
\tcode{T}. If \tcode{T} is an lvalue reference to object type, the result is an
lvalue;
if \tcode{T} is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the
lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array},
and function-to-pointer\iref{conv.func} standard conversions are
performed on the expression \tcode{v}.
The temporary materialization conversion\iref{conv.rval} is not
performed on \tcode{v}, other than as specified below.
Conversions that can be performed explicitly using
\keyword{const_cast} are listed below. No other conversion shall be
performed explicitly using \keyword{const_cast}.

\pnum
\begin{note}
Subject to the restrictions in this subclause, an expression can be cast
to its own type using a \keyword{const_cast} operator.
\end{note}

\pnum
For two similar object pointer or pointer to data member types
\tcode{T1} and \tcode{T2}\iref{conv.qual},
a prvalue of type \tcode{T1} can be explicitly
converted to the type \tcode{T2} using a \keyword{const_cast}
if, considering the qualification-decompositions of both types,
each $P^1_i$ is the same as $P^2_i$ for all $i$.
If \tcode{v} is a null pointer or null member pointer,
the result is a null pointer or null member pointer, respectively.
Otherwise, the result points to or past the end of the same object, or
points to the same member, respectively, as \tcode{v}.

\pnum
For two object types \tcode{T1} and \tcode{T2}, if a pointer to \tcode{T1} can
be explicitly converted to the type ``pointer to \tcode{T2}'' using a
\keyword{const_cast}, then the following conversions can also be made:
\begin{itemize}
\item an lvalue of type \tcode{T1} can be explicitly converted to an lvalue
of type \tcode{T2} using the cast \tcode{\keyword{const_cast}<T2\&>};

\item a glvalue of type \tcode{T1} can be explicitly converted to an xvalue
of type \tcode{T2} using the cast \tcode{\keyword{const_cast}<T2\&\&>}; and

\item if \tcode{T1} is a class or array type,
a prvalue of type \tcode{T1} can be
explicitly converted to an xvalue of type \tcode{T2} using the cast
\tcode{\keyword{const_cast}<T2\&\&>}.
The temporary materialization conversion is performed on \tcode{v}.
\end{itemize}

The result refers to the same object as the (possibly converted) operand.
\begin{example}
\begin{codeblock}
typedef int *A[3];                  // array of 3 pointer to \tcode{int}
typedef const int *const CA[3];     // array of 3 const pointer to \tcode{const int}

auto &&r2 = const_cast<A&&>(CA{});  // OK, temporary materialization conversion is performed
\end{codeblock}
\end{example}

\pnum
\begin{note}
Depending on the type of the object, a write operation through the
pointer, lvalue or pointer to data member resulting from a
\keyword{const_cast} that casts away a const-qualifier
\begin{footnote}
\keyword{const_cast}
is not limited to conversions that cast away a
const-qualifier.
\end{footnote}
can produce undefined behavior\iref{dcl.type.cv}.
\end{note}

\pnum
\indextext{\idxcode{const}!cast away}%
A conversion from a type \tcode{T1} to a type \tcode{T2}
\defnx{casts away constness}{casting away constness}
if \tcode{T1} and \tcode{T2} are different,
there is a qualification-decomposition\iref{conv.qual} of \tcode{T1}
yielding \placeholder{n} such that
\tcode{T2} has a qualification-decomposition of the form
\begin{indented}
$\cv{}_0^2$ $P_0^2$ $\cv{}_1^2$ $P_1^2$ $\cdots$ $\cv{}_{n-1}^2$ $P_{n-1}^2$ $\cv{}_n^2$ $\mathtt{U}_2$,
\end{indented}
and there is no qualification conversion that converts \tcode{T1} to
\begin{indented}
$\cv{}_0^2$ $P_0^1$ $\cv{}_1^2$ $P_1^1$ $\cdots$ $\cv{}_{n-1}^2$ $P_{n-1}^1$ $\cv{}_n^2$ $\mathtt{U}_1$.
\end{indented}

\pnum
Casting from an lvalue of type \tcode{T1} to an lvalue of type
\tcode{T2} using an lvalue reference cast
or casting from an expression of type \tcode{T1} to an xvalue of type \tcode{T2} using
an rvalue reference cast
casts away constness if a cast from a prvalue of type ``pointer to \tcode{T1}'' to the type ``pointer to
\tcode{T2}'' casts away constness.

\pnum
\begin{note}
Some conversions which involve only changes in cv-qualification cannot
be done using \keyword{const_cast}. For instance, conversions between
pointers to functions are not covered because such conversions lead to
values whose use causes undefined behavior. For the same reasons,
conversions between pointers to member functions, and in particular, the
conversion from a pointer to a const member function to a pointer to a
non-const member function, are not covered.
\end{note}
\indextext{expression!postfix|)}

\rSec2[expr.unary]{Unary expressions}

\rSec3[expr.unary.general]{General}

\pnum
\indextext{expression!unary|(}%
Expressions with unary operators group right-to-left.

\indextext{expression!unary}%
\indextext{operator!unary}%
\indextext{operator!\idxcode{sizeof}}%
\indextext{operator!cast}%
%
\begin{bnf}
%% Ed. note: character protrusion would misalign operators.
\microtypesetup{protrusion=false}
\nontermdef{unary-expression}\br
    postfix-expression\br
    unary-operator cast-expression\br
    \terminal{++} cast-expression\br
    \terminal{--} cast-expression\br
    await-expression\br
    \keyword{sizeof} unary-expression\br
    \keyword{sizeof} \terminal{(} type-id \terminal{)}\br
    \keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br
    \keyword{alignof} \terminal{(} type-id \terminal{)}\br
    noexcept-expression\br
    new-expression\br
    delete-expression\br
    reflect-expression
\end{bnf}

\indextext{operator!indirection}%
\indextext{\idxcode{*}|see{operator, indirection}}%
\indextext{operator!address-of}%
\indextext{\idxcode{\&}|see{operator, address-of}}%
\indextext{operator!unary minus}%
\indextext{\idxcode{-}|see{operator, unary minus}}%
\indextext{operator!unary plus}%
\indextext{\idxcode{+}|see{operator, unary plus}}%
\indextext{operator!logical negation}%
\indextext{\idxcode{"!}|see{operator, logical negation}}%
\indextext{operator!ones' complement}%
\indextext{~@\tcode{\~}|see{operator, ones' complement}}%
\indextext{operator!increment}%
\indextext{operator!decrement}%
%
\begin{bnf}
%% Ed. note: character protrusion would misalign operators.
\microtypesetup{protrusion=false}
\nontermdef{unary-operator} \textnormal{one of}\br
    \terminal{*  \&  +  -  !  \~}
\end{bnf}

\rSec3[expr.unary.op]{Unary operators}

\pnum
\indextext{expression!unary operator}%
\indextext{operator!unary}%
The unary \tcode{*} operator performs \defn{indirection}.
\indextext{dereferencing|see{indirection}}%
Its operand shall be a prvalue of type ``pointer to \tcode{T}'',
where \tcode{T} is an object or function type.
The operator yields an lvalue of type \tcode{T}.
If the operand points to an object or function,
the result denotes that object or function;
otherwise, the behavior is undefined except as specified in \ref{expr.typeid}.
\begin{note}
Indirection through a pointer to an out-of-lifetime object is valid\iref{basic.life}.
\end{note}
\begin{note}
\indextext{type!incomplete}%
Indirection through a pointer to an incomplete type (other than
\cv{} \keyword{void}) is valid. The lvalue thus obtained can be
used in limited ways (to initialize a reference, for example); this
lvalue must not be converted to a prvalue, see~\ref{conv.lval}.
\end{note}

\pnum
Each of the following unary operators yields a prvalue.

\pnum
\indextext{name!address of cv-qualified}%
\indextext{expression!pointer-to-member constant}%
The operand of the unary \tcode{\&} operator
shall be an lvalue of some type \tcode{T}.
\begin{itemize}
\item
If the operand is a \grammarterm{qualified-id} or \grammarterm{splice-expression}
designating a non-static member \tcode{m},
other than an explicit object member function,
\tcode{m} shall be a direct member of some class \tcode{C}
that is not an anonymous union.
The result has type ``pointer to member of class \tcode{C} of type \tcode{T}''
and designates \tcode{C::m}.
\begin{note}
A \grammarterm{qualified-id}
that names a member of a namespace-scope anonymous union
is considered to be a class member access expression\iref{expr.prim.id.general}
and cannot be used to form a pointer to member.
\end{note}
\item
Otherwise, the result has type ``pointer to \tcode{T}'' and points to
the designated object\iref{intro.memory} or function\iref{basic.compound}.
If the operand designates an explicit object member function\iref{dcl.fct},
the operand shall be
a \grammarterm{qualified-id} or a \grammarterm{splice-expression}.
\begin{note}
In particular, taking the address of a variable of type ``\cv{}~\tcode{T}''
yields a pointer of type ``pointer to \cv{}~\tcode{T}''.
\end{note}
\end{itemize}
\begin{example}
\begin{codeblock}
struct A { int i; };
struct B : A { };
... &B::i ...       // has type \tcode{int A::*}
int a;
int* p1 = &a;
int* p2 = p1 + 1;   // defined behavior
bool b = p2 > p1;   // defined behavior, with value \tcode{true}
\end{codeblock}
\end{example}
\begin{note}
A pointer to member formed from a \keyword{mutable} non-static data
member\iref{dcl.stc} does not reflect the \keyword{mutable} specifier
associated with the non-static data member.
\end{note}

\pnum
A pointer to member is only formed when an explicit \tcode{\&} is used
and its operand is
a \grammarterm{qualified-id} or \grammarterm{splice-expression}
not enclosed in parentheses.
\begin{note}
That is, the expression \tcode{\&(qualified-id)}, where the
\grammarterm{qualified-id} is enclosed in parentheses, does not form an
expression of type ``pointer to member''. Neither does
\tcode{qualified-id}, because there is no implicit conversion from a
\grammarterm{qualified-id} for a non-static member function to the type
``pointer to member function'' as there is from an lvalue of function
type to the type ``pointer to function''\iref{conv.func}. Nor is
\tcode{\&unqualified-id} a pointer to member, even within the scope of
the \grammarterm{unqualified-id}'s class.
\end{note}

\pnum
If \tcode{\&} is applied to an lvalue of incomplete class type and the
complete type declares \tcode{\keyword{operator}\&()}, it is unspecified whether
the operator has the built-in meaning or the operator function is
called. The operand of \tcode{\&} shall not be a bit-field.

\pnum
\indextext{overloaded function!address of}%
\begin{note}
The address of an overload set\iref{over} can be taken
only in a context that uniquely determines
which function is referred to (see~\ref{over.over}).
Since the context can affect whether the operand is a static or
non-static member function, the context can also affect whether the
expression has type ``pointer to function'' or ``pointer to member
function''.
\end{note}

\pnum
\indextext{operator!unary plus}%
The operand of the unary \tcode{+} operator shall be a prvalue of
arithmetic, unscoped
enumeration, or pointer type and the result is the value of the
argument. Integral promotion is performed on integral or enumeration
operands. The type of the result is the type of the promoted operand.

\pnum
\indextext{operator!unary minus}%
The operand of the unary \tcode{-} operator shall be a prvalue of
arithmetic or unscoped
enumeration type and the result is the negative of its operand. Integral
promotion is performed on integral or enumeration operands. The negative
of an unsigned quantity is computed by subtracting its value from $2^n$,
where $n$ is the number of bits in the promoted operand. The type of the
result is the type of the promoted operand.
\begin{note}
The result is the two's complement of the operand
(where operand and result are considered as unsigned).
\end{note}

\pnum
\indextext{operator!logical negation}%
The operand of the logical negation operator \tcode{!} is contextually
converted to \keyword{bool}\iref{conv};
its value is \keyword{true}
if the converted operand is \keyword{false} and \keyword{false} otherwise.
The type of the result is \keyword{bool}.

\pnum
\indextext{operator!ones' complement}%
The operand of the \tcode{\~{}} operator shall be a prvalue of
integral or unscoped enumeration type.
Integral promotions are performed.
The type of the result is the type of the promoted operand.
% FIXME: [basic.fundamental]/p5 uses $x_i$; [expr] uses $\tcode{x}_i$.
Given the coefficients $\tcode{x}_i$
of the base-2 representation\iref{basic.fundamental}
of the promoted operand \tcode{x},
the coefficient $\tcode{r}_i$
of the base-2 representation of the result \tcode{r}
is 1 if $\tcode{x}_i$ is 0, and 0 otherwise.
\begin{note}
The result is the ones' complement of the operand
(where operand and result are considered as unsigned).
\end{note}
There is an ambiguity
in the grammar when \tcode{\~{}} is followed by
a \grammarterm{type-name} or \grammarterm{computed-type-specifier}.
The ambiguity is resolved by treating \tcode{\~{}} as the
operator rather than as the start of an \grammarterm{unqualified-id}
naming a destructor.
\begin{note}
Because the grammar does not permit an operator to follow the
\tcode{.}, \tcode{->}, or \tcode{::} tokens, a \tcode{\~{}} followed by
a \grammarterm{type-name} or \grammarterm{computed-type-specifier} in a
member access expression or \grammarterm{qualified-id} is
unambiguously parsed as a destructor name.
\end{note}

\rSec3[expr.pre.incr]{Increment and decrement}

\pnum
\indextext{expression!increment}%
\indextext{expression!decrement}%
\indextext{operator!increment}%
\indextext{operator!decrement}%
\indextext{prefix \tcode{++}}%
\indextext{prefix \tcode{--}}%
The operand of prefix \tcode{++} or \tcode{--}
shall not be of type \cv{}~\tcode{bool}.
An operand with volatile-qualified type is deprecated;
see~\ref{depr.volatile.type}.
The expression \tcode{++x} is otherwise equivalent to \tcode{x+=1} and
the expression \tcode{--x} is otherwise equivalent to \tcode{x-=1}\iref{expr.assign}.
\begin{note}
For postfix increment and decrement, see~\ref{expr.post.incr}.
\end{note}

\rSec3[expr.await]{Await}
\indextext{expression!await}%
\indextext{\idxcode{co_await}}%

\pnum
The \keyword{co_await} expression is used to suspend evaluation of a
coroutine\iref{dcl.fct.def.coroutine} while awaiting completion of
the computation represented by the operand expression.
Suspending the evaluation of a coroutine
transfers control to its caller or resumer.

\begin{bnf}
\nontermdef{await-expression}\br
    \keyword{co_await} cast-expression
\end{bnf}

\pnum
An \grammarterm{await-expression} shall appear only as a potentially evaluated
expression within the \grammarterm{compound-statement} of a
\grammarterm{function-body} or \grammarterm{lambda-expression},
in either case
outside of a \grammarterm{handler}\iref{except.pre}.
In a \grammarterm{declaration-statement} or in the
\grammarterm{simple-declaration} (if any)
of an \grammarterm{init-statement}, an \grammarterm{await-expression}
shall appear only in an \grammarterm{initializer} of that
\grammarterm{declaration-statement} or \grammarterm{simple-declaration}.
An \grammarterm{await-expression} shall not appear in a
default argument\iref{dcl.fct.default}.
An \grammarterm{await-expression} shall not appear in the initializer of
a block variable with static or thread storage duration.
An \grammarterm{await-expression} shall not be
a potentially-evaluated subexpression
of the predicate of a contract assertion\iref{basic.contract}.
A context within a function where an \grammarterm{await-expression} can appear
is called a \term{suspension context} of the function.

\pnum
Evaluation of an \grammarterm{await-expression} involves the following
auxiliary types, expressions, and objects:

\begin{itemize}
\item
\placeholder{p} is an lvalue naming the promise
object\iref{dcl.fct.def.coroutine}
of the enclosing coroutine and \tcode{P} is the type of that object.

\item Unless
the \grammarterm{await-expression} was implicitly produced by
a \grammarterm{yield-expression}\iref{expr.yield},
an initial await expression,
or a final await expression\iref{dcl.fct.def.coroutine},
a search is performed for the name \tcode{await_transform}
in the scope of \tcode{P}\iref{class.member.lookup}.
If this search is performed and finds at least one declaration,
then \placeholder{a} is
\mbox{\placeholder{p}\tcode{.await_transform(}\grammarterm{cast-expression}\tcode{)}};
otherwise, \placeholder{a} is the  \grammarterm{cast-expression}.

\item
\placeholder{o} is determined by enumerating the applicable
\tcode{\keyword{operator} \keyword{co_await}} functions for an argument
\placeholder{a}\iref{over.match.oper}, and choosing the best one through
overload resolution\iref{over.match}. If overload resolution is ambiguous,
the program is ill-formed.
If no viable functions are found, \placeholder{o} is \placeholder{a}.
Otherwise, \placeholder{o} is a call to the selected function
with the argument \placeholder{a}.
If \placeholder{o} would be a prvalue,
the temporary materialization conversion\iref{conv.rval} is applied.

\item
\placeholder{e} is an lvalue
referring to the result of evaluating
the (possibly-converted) \placeholder{o}.

\item
% FIXME: h needs to be an expression so we can use it as an argument
% to await_suspend. What should its value category be?
% Don't forget to remove "and objects" from the intro sentence when
% this is fixed.
\placeholder{h} is an object of type
\tcode{std::coroutine_handle<P>}
referring to the enclosing coroutine.

\item
\placeholder{await-ready} is the expression
\placeholder{e}\tcode{.await_ready()},
contextually converted to \tcode{bool}.

\item
\placeholder{await-suspend} is the expression
\placeholder{e}\tcode{.await_suspend(}\placeholder{h}\tcode{)},
which shall be a prvalue of type \keyword{void}, \keyword{bool}, or
\tcode{std::coroutine_handle<Z>} for some type \tcode{Z}.

\item
\placeholder{await-resume} is the expression
\placeholder{e}\tcode{.await_resume()}.
\end{itemize}

\pnum
The \grammarterm{await-expression} has the same type and value category
as the \placeholder{await-resume} expression.

\pnum
The \grammarterm{await-expression} evaluates
the (possibly-converted) \placeholder{o} expression and
the \placeholder{await-ready} expression, then:
\begin{itemize}
\item
If the result of \placeholder{await-ready} is \keyword{false},
the coroutine is considered suspended.
Then:
\begin{itemize}
\item
If the type of \placeholder{await-suspend}
is \tcode{std::coroutine_handle<Z>},
\placeholder{await-suspend}\tcode{.resume()} is evaluated.
\begin{note}
This resumes the coroutine referred to
by the result of \placeholder{await-suspend}.
Any number of coroutines can be successively resumed in this fashion,
eventually returning control flow to the current coroutine caller or
resumer\iref{dcl.fct.def.coroutine}.
\end{note}

\item
Otherwise, if the type of \placeholder{await-suspend}
is \keyword{bool},
\placeholder{await-suspend} is evaluated,
and the coroutine is resumed if the result is \keyword{false}.

\item
Otherwise, \placeholder{await-suspend} is evaluated.
\end{itemize}
If the evaluation of \placeholder{await-suspend}
exits via an exception, the exception is caught,
the coroutine is resumed, and the exception is immediately
rethrown\iref{except.throw}. Otherwise, control flow returns
to the current coroutine caller or resumer\iref{dcl.fct.def.coroutine}
without exiting any scopes\iref{stmt.jump}.
\indextext{coroutine!suspend point}%
The point in the coroutine
immediately prior to control returning to its caller or resumer
is a coroutine \defn{suspend point}.

\item
If the result of \placeholder{await-ready} is \keyword{true},
or when the coroutine is resumed
other than by rethrowing an exception from \placeholder{await-suspend},
the \placeholder{await-resume} expression is evaluated, and
its result is the result of the \grammarterm{await-expression}.
\end{itemize}
\begin{note}
With respect to sequencing,
an \grammarterm{await-expression} is indivisible\iref{intro.execution}.
\end{note}

\pnum
\begin{example}
\begin{codeblock}
template <typename T>
struct my_future {
  @\commentellip@
  bool await_ready();
  void await_suspend(std::coroutine_handle<>);
  T await_resume();
};

template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> d) {
  struct awaiter {
    std::chrono::system_clock::duration duration;
    @\commentellip@
    awaiter(std::chrono::system_clock::duration d) : duration(d) {}
    bool await_ready() const { return duration.count() <= 0; }
    void await_resume() {}
    void await_suspend(std::coroutine_handle<> h) { @\commentellip@ }
  };
  return awaiter{d};
}

using namespace std::chrono;

my_future<int> h();

my_future<void> g() {
  std::cout << "just about to go to sleep...\n";
  co_await 10ms;
  std::cout << "resumed\n";
  co_await h();
}

auto f(int x = co_await h());   // error: \grammarterm{await-expression} outside of function suspension context
int a[] = { co_await h() };     // error: \grammarterm{await-expression} outside of function suspension context
\end{codeblock}
\end{example}

\rSec3[expr.sizeof]{Sizeof}

\pnum
\indextext{expression!\idxcode{sizeof}}%
\indextext{operator!\idxcode{sizeof}}%
\indextext{byte}%
The \keyword{sizeof} operator yields the number of bytes
occupied by a non-potentially-overlapping object of the type
of its operand. The operand is either an expression,
which is an unevaluated operand\iref{term.unevaluated.operand}, or a parenthesized
\grammarterm{type-id}.
\indextext{type!incomplete}%
The \keyword{sizeof} operator shall not be applied to an expression that
has function or incomplete type,
to the parenthesized name of such
types, or to a glvalue that designates a bit-field.
The result of \keyword{sizeof}
applied to any of the narrow character types is \tcode{1}.
The result of
\keyword{sizeof} applied to any other fundamental
type\iref{basic.fundamental} is \impldef{\tcode{sizeof} applied to
fundamental types
other than \tcode{char}, \tcode{signed char}, and \tcode{unsigned char}}.
\begin{note}
In particular, the values of \tcode{\keyword{sizeof}(\keyword{bool})}, \tcode{\keyword{sizeof}(\keyword{char16_t})},
\tcode{\keyword{sizeof}(\keyword{char32_t})}, and \tcode{\keyword{sizeof}(\keyword{wchar_t})} are
implementation-defined.
\begin{footnote}
\tcode{\keyword{sizeof}(\keyword{bool})} is not required to be \tcode{1}.
\end{footnote}
\end{note}
\begin{note}
See~\ref{intro.memory} for the definition of byte
and~\ref{term.object.representation} for the definition of object representation.
\end{note}

\pnum
\indextext{reference!\idxcode{sizeof}}%
When applied to a reference type, the result is the size
of the referenced type.
\indextext{class object!\idxcode{sizeof}}%
When applied to a class, the result is the number of bytes in an object
of that class including any padding required for placing objects of that
type in an array.
The amount and placement of padding in a class type
is a property of the implementation.
The result of applying \keyword{sizeof} to a
potentially-overlapping subobject is
the size of the type, not the size of the subobject.
\begin{footnote}
The actual size of a potentially-overlapping subobject
can be less than the result of
applying \keyword{sizeof} to the subobject, due to virtual base classes
and less strict padding requirements on potentially-overlapping subobjects.
\end{footnote}
\indextext{array!\idxcode{sizeof}}%
When applied to an array, the result is the total number of bytes in the
array. This implies that the size of an array of $n$ elements is
$n$ times the size of an element.

\pnum
The lvalue-to-rvalue\iref{conv.lval},
array-to-pointer\iref{conv.array}, and
function-to-pointer\iref{conv.func} standard conversions are not
applied to the operand of \keyword{sizeof}.
If the operand is a prvalue,
the temporary materialization conversion\iref{conv.rval}
is applied.

\pnum
The \grammarterm{identifier} in a \tcode{\keyword{sizeof}...} expression shall name a
pack. The \tcode{\keyword{sizeof}...} operator yields the number of elements
in the pack\iref{temp.variadic}.
A \tcode{\keyword{sizeof}...} expression is a pack expansion\iref{temp.variadic}.
\begin{example}
\begin{codeblock}
template<class... Types>
struct count {
  static constexpr std::size_t value = sizeof...(Types);
};
\end{codeblock}
\end{example}

\pnum
\indextext{\idxcode{size_t}}%
\indexlibraryglobal{size_t}%
The result of \keyword{sizeof} and \tcode{\keyword{sizeof}...} is a prvalue of type
\tcode{std::size_t}.
\begin{note}
A \keyword{sizeof} expression
is an integral constant expression\iref{expr.const.const}.
The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header
\libheader{cstddef}\iref{cstddef.syn,support.types.layout}.
\end{note}

\rSec3[expr.alignof]{Alignof}

\pnum
\indextext{\idxcode{alignof}}%
\indextext{expression!\idxcode{alignof}}%
An \keyword{alignof} expression yields the alignment requirement
of its operand type. The operand shall be a \grammarterm{type-id}
representing a complete object type, or an array thereof, or a reference
to one of those types.

\pnum
The result is a prvalue of type \tcode{std::size_t}.
\begin{note}
An \keyword{alignof} expression
is an integral constant expression\iref{expr.const.const}.
The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header
\libheader{cstddef}\iref{cstddef.syn,support.types.layout}.
\end{note}

\pnum
When \keyword{alignof} is applied to a reference type, the result
is the alignment of the referenced type. When \keyword{alignof}
is applied to an array type, the result is the alignment of the
element type.

\rSec3[expr.unary.noexcept]{\tcode{noexcept} operator}

\indextext{\idxcode{noexcept}}%
\indextext{expression!\idxcode{noexcept}}%

\begin{bnf}
\nontermdef{noexcept-expression}\br
  \keyword{noexcept} \terminal{(} expression \terminal{)}
\end{bnf}

\pnum
The operand of the \keyword{noexcept} operator
is an unevaluated operand\iref{term.unevaluated.operand}.
If the operand is a prvalue,
the temporary materialization conversion\iref{conv.rval} is applied.

\pnum
The result of the \keyword{noexcept} operator is a prvalue of type \keyword{bool}.
The result is \tcode{false} if
the full-expression of the operand is potentially-throwing\iref{except.spec}, and
\tcode{true} otherwise.
\begin{note}
A \grammarterm{noexcept-expression}
is an integral constant expression\iref{expr.const.const}.
\end{note}
\indextext{expression!unary|)}

\rSec3[expr.new]{New}

\pnum
\indextext{expression!\idxcode{new}}%
\indextext{free store|seealso{\tcode{new}}}%
\indextext{free store|seealso{\tcode{delete}}}%
\indextext{memory management|see{\tcode{new}}}%
\indextext{memory management|see{\tcode{delete}}}%
\indextext{storage management|see{\tcode{new}}}%
\indextext{storage management|see{\tcode{delete}}}%
\indextext{\idxcode{new}}%
The \grammarterm{new-expression} attempts to create an object of the
\grammarterm{type-id} or \grammarterm{new-type-id}\iref{dcl.name} to which
it is applied. The type of that object is the \defnadj{allocated}{type}.
\indextext{type!incomplete}%
This type shall be a complete object type\iref{term.incomplete.type},
but not an abstract class type\iref{class.abstract} or array
thereof\iref{intro.object}.
\begin{note}
Because references are not objects, references cannot be created by
\grammarterm{new-expression}{s}.
\end{note}
\begin{note}
The \grammarterm{type-id} can be a cv-qualified type, in which case the
object created by the \grammarterm{new-expression} has a cv-qualified type.
\end{note}

\begin{bnf}
\nontermdef{new-expression}\br
    \opt{\terminal{::}} \keyword{new} \opt{new-placement} new-type-id \opt{new-initializer} \br
    \opt{\terminal{::}} \keyword{new} \opt{new-placement} \terminal{(} type-id \terminal{)} \opt{new-initializer}
\end{bnf}

\indextext{\idxcode{new}!storage allocation}%
%
\begin{bnf}
\nontermdef{new-placement}\br
    \terminal{(} expression-list \terminal{)}
\end{bnf}

\begin{bnf}
\nontermdef{new-type-id}\br
    type-specifier-seq \opt{new-declarator}
\end{bnf}

\begin{bnf}
\nontermdef{new-declarator}\br
    ptr-operator \opt{new-declarator} \br
    noptr-new-declarator
\end{bnf}

\begin{bnf}
\nontermdef{noptr-new-declarator}\br
    \terminal{[} \opt{expression} \terminal{]} \opt{attribute-specifier-seq}\br
    noptr-new-declarator \terminal{[} constant-expression \terminal{]} \opt{attribute-specifier-seq}
\end{bnf}

\begin{bnf}
\nontermdef{new-initializer}\br
    \terminal{(} \opt{expression-list} \terminal{)}\br
    braced-init-list
\end{bnf}

\pnum
If a placeholder type\iref{dcl.spec.auto} or
a placeholder for a deduced class type\iref{dcl.type.class.deduct}
appears in the
\grammarterm{type-specifier-seq} of a \grammarterm{new-type-id} or
\grammarterm{type-id} of a \grammarterm{new-expression},
the allocated type is deduced as follows:
Let
\placeholder{init} be the \grammarterm{new-initializer}, if any,
and
\tcode{T} be the \grammarterm{new-type-id} or \grammarterm{type-id} of
the \grammarterm{new-expression}, then the allocated type is the type
deduced for the variable \tcode{x} in the invented
declaration\iref{dcl.spec.auto}:

\begin{codeblock}
T x @\textrm{\placeholder{init}}@ ;
\end{codeblock}

\begin{example}
\begin{codeblock}
new auto(1);                    // allocated type is \tcode{int}
auto x = new auto('a');         // allocated type is \tcode{char}, \tcode{x} is of type \tcode{char*}

template<class T> struct A { A(T, T); };
auto y = new A{1, 2};           // allocated type is \tcode{A<int>}
\end{codeblock}
\end{example}

\pnum
The \grammarterm{new-type-id} in a \grammarterm{new-expression} is the longest
possible sequence of \grammarterm{new-declarator}{s}.
\begin{note}
This prevents ambiguities between the declarator operators \tcode{\&}, \tcode{\&\&},
\tcode{*}, and \tcode{[]} and their expression counterparts.
\end{note}
\begin{example}
\begin{codeblock}
new int * i;                    // syntax error: parsed as \tcode{(new int*) i}, not as \tcode{(new int)*i}
\end{codeblock}
The \tcode{*} is the pointer declarator and not the multiplication
operator.
\end{example}

\pnum
\begin{note}
\indextext{ambiguity!parentheses and}%
Parentheses in a \grammarterm{new-type-id} of a \grammarterm{new-expression}
can have surprising effects.
\begin{example}
\begin{codeblock}
new int(*[10])();               // error
\end{codeblock}
is ill-formed because the binding is
\begin{codeblock}
(new int) (*[10])();            // error
\end{codeblock}

Instead, the explicitly parenthesized version of the \keyword{new}
operator can be used to create objects of compound
types\iref{basic.compound}:

\begin{codeblock}
new (int (*[10])());
\end{codeblock}
allocates an array of \tcode{10} pointers to functions (taking no
argument and returning \tcode{int}).
\end{example}
\end{note}

\pnum
The \grammarterm{attribute-specifier-seq} in a \grammarterm{noptr-new-declarator} appertains
to the associated array type.

\pnum
Every \grammarterm{constant-expression} in a
\grammarterm{noptr-new-declarator} shall be a converted constant
expression\iref{expr.const.const} of type \tcode{std::size_t} and
its value shall be greater than zero.
\begin{example}
Given the definition \tcode{int n = 42},
\tcode{new float[n][5]} is well-formed (because \tcode{n} is the
\grammarterm{expression} of a \grammarterm{noptr-new-declarator}), but
\tcode{new float[5][n]} is ill-formed (because \tcode{n} is not a
constant expression).
Furthermore,
\tcode{new float[0]} is well-formed
(because \tcode{0} is the \grammarterm{expression}
of a \grammarterm{noptr-new-declarator},
where a value of zero results in the allocation of an array with no elements),
but \tcode{new float[n][0]} is ill-formed
(because \tcode{0} is the \grammarterm{constant-expression}
of a \grammarterm{noptr-new-declarator},
where only values greater than zero are allowed).
\end{example}

\pnum
If the \grammarterm{type-id} or \grammarterm{new-type-id}
denotes an array type of unknown bound\iref{dcl.array},
the \grammarterm{new-initializer} shall not be omitted;
the allocated object is an array with \tcode{n} elements,
where \tcode{n} is determined from the number of initial elements
supplied in
the \grammarterm{new-initializer}\iref{dcl.init.aggr,dcl.init.string}.

\pnum
\indextext{\idxcode{new}}%
If the \grammarterm{expression} in a \grammarterm{noptr-new-declarator}
is present, it is implicitly converted to \tcode{std::size_t}.
\indextext{function!allocation}%
The value of the \grammarterm{expression} is invalid if
\begin{itemize}
\item
the expression is of non-class type and its value before converting to
\tcode{std::size_t} is less than zero;

\item
the expression is of class type and its value before application of the second
standard conversion\iref{over.ics.user}
\begin{footnote}
If the conversion function
returns a signed integer type, the second standard conversion converts to the
unsigned type \tcode{std::size_t} and thus thwarts any attempt to detect a
negative value afterwards.
\end{footnote}
is less than zero;

\item
its value is such that the size of the allocated object would exceed the
\impldef{maximum size of an allocated object} limit\iref{implimits}; or

\item
the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}
or a parenthesized \grammarterm{expression-list} and the
number of array elements for which initializers are provided (including the
terminating \tcode{'\textbackslash 0'} in a \grammarterm{string-literal}\iref{lex.string}) exceeds the
number of elements to initialize.
\end{itemize}

If the value of the \grammarterm{expression} is invalid after converting to \tcode{std::size_t}:
\begin{itemize}
\item
if the \grammarterm{expression} is a potentially evaluated core constant expression,
the program is ill-formed;
\item
otherwise, an allocation function is not called; instead
\begin{itemize}
\item
if the allocation function that would have been called
has a non-throwing exception specification\iref{except.spec},
the value of the \grammarterm{new-expression}
is the null pointer value of the required result type;
\item
otherwise, the \grammarterm{new-expression} terminates by throwing an
exception of a type that would match a handler\iref{except.handle} of type
\tcode{std::bad_array_new_length}\iref{new.badlength}.
\end{itemize}
\end{itemize}
When the value of the \grammarterm{expression} is zero, the allocation
function is called to allocate an array with no elements.

\pnum
If the allocated type is an array,
the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}
or a parenthesized \grammarterm{expression-list}, and
the \grammarterm{expression}
is potentially evaluated and not a core constant expression,
the semantic constraints of initializing a hypothetical element of
the array are checked as follows:
\begin{itemize}
\item
If the \grammarterm{new-initializer} is a \grammarterm{braced-init-list},
the hypothetical element is copy-initialized
from an empty initializer list\iref{dcl.init.list}.
\item
Otherwise, the hypothetical element is value-initialized\iref{dcl.init.general}.
\end{itemize}
\begin{note}
The array can contain more elements than there are
elements in the \grammarterm{new-initializer},
requiring initialization of the remainder of the array elements as appropriate.
\end{note}

\pnum
\indextext{storage duration!dynamic}%
Objects created by a \grammarterm{new-expression} have dynamic storage
duration\iref{basic.stc.dynamic}.
\begin{note}
\indextext{\idxcode{new}!scoping and}%
The lifetime of such an object is not necessarily restricted to the
scope in which it is created.
\end{note}

\pnum
\indextext{array!\idxcode{new}}%
When the allocated type is ``array of \tcode{N} \tcode{T}''
(that is, the \grammarterm{noptr-new-declarator} syntax is used or the
\grammarterm{new-type-id} or \grammarterm{type-id} denotes an array type),
the \grammarterm{new-expression} yields a prvalue of type ``pointer to \tcode{T}''
that points to the initial element (if any) of the array.
Otherwise, let \tcode{T} be the allocated type;
the \grammarterm{new-expression}
is a prvalue of type ``pointer to T''
that points to the object created.
\begin{note}
Both \tcode{\keyword{new} \keyword{int}} and \tcode{\keyword{new} \keyword{int}[10]} have type \tcode{\keyword{int}*} and
the type of \tcode{\keyword{new} \keyword{int}[i][10]} is \tcode{\keyword{int} (*)[10]}.
\end{note}

\pnum
A \grammarterm{new-expression} may obtain storage for the object by calling an
allocation function\iref{basic.stc.dynamic.allocation}. If
the \grammarterm{new-expression} terminates by throwing an exception, it
may release storage by calling a deallocation
function\iref{basic.stc.dynamic.deallocation}. If the allocated type
is a non-array type, the allocation function's name is
\indextext{\idxcode{operator new}}%
\indextext{\idxcode{operator delete}}%
\tcode{\keyword{operator} \keyword{new}} and the deallocation function's name is
\tcode{\keyword{operator} \keyword{delete}}. If the allocated type is an array type, the
allocation function's name is
\indextext{\idxcode{operator new}}%
\indextext{\idxcode{operator delete}}%
\tcode{\keyword{operator} \keyword{new}[]}
and the deallocation function's name is
\tcode{\keyword{operator} \keyword{delete}[]}.
\begin{note}
An implementation is expected to provide default definitions for the global
allocation
functions\iref{basic.stc.dynamic,new.delete.single,new.delete.array}.
A \Cpp{} program can provide alternative definitions of
these functions\iref{replacement.functions} and/or class-specific
versions\iref{class.free}.
The set of allocation and deallocation functions that can be called
by a \grammarterm{new-expression}
can include functions that do not perform allocation or deallocation;
for example, see \ref{new.delete.placement}.
\end{note}

\pnum
\indextext{operator!scope resolution}%
If the \grammarterm{new-expression}
does not begin with a unary \tcode{::} operator and
the allocated type is a class type \tcode{T} or array thereof,
a search is performed for the allocation function's name in the scope
of \tcode{T}\iref{class.member.lookup}.
Otherwise, or if nothing is found,
the allocation function's name is looked up by
searching for it in the global scope.

\pnum
An implementation is allowed to omit a call to a replaceable global allocation
function\iref{new.delete.single,new.delete.array}. When it does so,
the storage is instead provided by the implementation or provided by extending
the allocation of another \grammarterm{new-expression}.

\pnum
During an evaluation of a constant expression,
a call to a replaceable allocation function is always omitted\iref{expr.const.core}.

\pnum
The implementation may
extend the allocation of a \grammarterm{new-expression} \tcode{e1} to provide
storage for a \grammarterm{new-expression} \tcode{e2} if the
following would be true were the allocation not extended:
\begin{itemize}
\item the evaluation of \tcode{e1} is sequenced before the evaluation of
\tcode{e2}, and

\item \tcode{e2} is evaluated whenever \tcode{e1} obtains storage, and

\item both \tcode{e1} and \tcode{e2} invoke the same replaceable global
allocation function, and

\item if the allocation function invoked by \tcode{e1} and \tcode{e2} is
throwing, any exceptions thrown in the evaluation of either \tcode{e1} or
\tcode{e2} would be first caught in the same handler, and

\item the pointer values produced by \tcode{e1} and \tcode{e2} are operands to
evaluated \grammarterm{delete-expression}{s}, and

\item the evaluation of \tcode{e2} is sequenced before the evaluation of the
\grammarterm{delete-expression} whose operand is the pointer value produced
by \tcode{e1}.
\end{itemize}

\begin{example}
\begin{codeblock}
void can_merge(int x) {
  // These allocations are safe for merging:
  std::unique_ptr<char[]> a{new (std::nothrow) char[8]};
  std::unique_ptr<char[]> b{new (std::nothrow) char[8]};
  std::unique_ptr<char[]> c{new (std::nothrow) char[x]};

  g(a.get(), b.get(), c.get());
}

void cannot_merge(int x) {
  std::unique_ptr<char[]> a{new char[8]};
  try {
    // Merging this allocation would change its catch handler.
    std::unique_ptr<char[]> b{new char[x]};
  } catch (const std::bad_alloc& e) {
    std::cerr << "Allocation failed: " << e.what() << std::endl;
    throw;
  }
}
\end{codeblock}
\end{example}

\pnum
When a \grammarterm{new-expression} calls an allocation function and that
allocation has not been extended, the
\grammarterm{new-expression} passes the amount of space requested to the
allocation function as the first argument of type
\tcode{std::size_t}. That argument shall be no less than the size
of the object being created; it may be greater than the size of the
object being created only if the object is an array and
the allocation function is not a non-allocating form\iref{new.delete.placement}.
For arrays of
\keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, and \tcode{std::byte},
the difference between the
result of the \grammarterm{new-expression} and the address returned by the
allocation function shall be an integral multiple of the
strictest fundamental
alignment requirement\iref{basic.align} of any object type whose size
is no greater than the size of the array being created.
\begin{note}
\indextext{allocation!alignment storage}%
Because allocation functions are assumed to return pointers to storage
that is appropriately aligned for objects of any type
with fundamental alignment, this constraint
on array allocation overhead permits the common idiom of allocating
character arrays into which objects of other types will later be placed.
\end{note}

\pnum
When a \grammarterm{new-expression} calls an allocation function and that
allocation has been extended, the size argument to the allocation call shall
be no greater than the sum of the sizes for the omitted calls as specified
above, plus the size for the extended call had it not been extended, plus any
padding necessary to align the allocated objects within the allocated memory.

\pnum
\indextext{placement new-expression@placement \gterm{new-expression}|see{\gterm{new-expression}, placement}}%
The \grammarterm{new-placement} syntax is used to supply additional
arguments to an allocation function; such an expression is called
a \defnx{placement \grammarterm{new-expression}}{\idxgram{new-expression}!placement}.

\pnum
Overload resolution is
performed on a function call created by assembling an argument list.
The first argument is
the amount of space requested,
and has type \tcode{std::size_t}.
If the type of the allocated object has new-extended alignment,
the next argument is
the type's alignment,
and has type \tcode{std::align_val_t}.
If the \grammarterm{new-placement} syntax is used,
the \grammarterm{initializer-clause}{s}
in its \grammarterm{expression-list}
are the succeeding arguments.
If no matching function is found then
\begin{itemize}

\item
if the allocated object type has new-extended alignment,
the alignment argument is removed from the argument list;

\item
otherwise, an argument that
is the type's alignment and has type \tcode{std::align_val_t}
is added into the argument list immediately after the first argument;

\end{itemize}
and then overload resolution is performed again.

\pnum
\begin{example}
\begin{itemize}
\item \tcode{new T} results in one of the following calls:
\begin{codeblock}
operator new(sizeof(T))
operator new(sizeof(T), std::align_val_t(alignof(T)))
\end{codeblock}
\item \tcode{new(2,f) T} results in one of the following calls:
\begin{codeblock}
operator new(sizeof(T), 2, f)
operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)
\end{codeblock}
\item \tcode{new T[5]} results in one of the following calls:
\begin{codeblock}
operator new[](sizeof(T) * 5 + x)
operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)))
\end{codeblock}
\item \tcode{new(2,f) T[5]} results in one of the following calls:
\begin{codeblock}
operator new[](sizeof(T) * 5 + x, 2, f)
operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)), 2, f)
\end{codeblock}
\end{itemize}
Here, each instance of \tcode{x} is a non-negative unspecified value
representing array allocation overhead; the result of the
\grammarterm{new-expression} will be offset by this amount from the value
returned by \tcode{operator new[]}. This overhead may be applied in all
array \grammarterm{new-expression}{s}, including those referencing
a placement allocation function, except when referencing
the library function \tcode{operator new[](std::size_t, void*)}.
The amount of overhead may vary from one
invocation of \keyword{new} to another.
\end{example}

\pnum
\begin{note}
Unless an allocation function has a non-throwing
exception specification\iref{except.spec},
it indicates failure to allocate storage by throwing a
\indextext{\idxcode{bad_alloc}}%
\indexlibraryglobal{bad_alloc}%
\tcode{std::bad_alloc}
exception\iref{basic.stc.dynamic.allocation,except.throw,bad.alloc};
it returns a non-null pointer otherwise. If the allocation function
has a non-throwing exception specification,
it returns null to indicate failure to allocate storage
and a non-null pointer otherwise.
\end{note}
If the allocation function is a non-allocating
form\iref{new.delete.placement} that returns null,
the behavior is undefined.
Otherwise,
if the allocation function returns null, initialization shall not be
done, the deallocation function shall not be called, and the value of
the \grammarterm{new-expression} shall be null.

\pnum
\begin{note}
When the allocation function returns a value other than null, it must be
a pointer to a block of storage in which space for the object has been
reserved. The block of storage is assumed to be
appropriately aligned\iref{basic.align}
and of the requested size. The address of the created object will not
necessarily be the same as that of the block if the object is an array.
\end{note}

\pnum
\indextext{\idxcode{new}!array of class objects and}%
\indextext{\idxcode{new}!initialization and}%
\indextext{\idxcode{new}!constructor and}%
\indextext{\idxcode{new}!default constructor and}%
A \grammarterm{new-expression} that creates an object of type \tcode{T}
initializes that object as follows:

\begin{itemize}
\item If the \grammarterm{new-initializer} is omitted, the object is
default-initialized\iref{dcl.init}.
\begin{note}
If no initialization
is performed, the object has an indeterminate value.
\end{note}

\item Otherwise, the \grammarterm{new-initializer} is interpreted according to
the initialization rules of~\ref{dcl.init} for direct-initialization.
\end{itemize}

\pnum
\indextext{\idxcode{new}!unspecified order of evaluation}%
\indextext{\idxcode{new}!unspecified constructor and}%
The invocation of the allocation function is sequenced before
the evaluations of expressions in the \grammarterm{new-initializer}. Initialization of
the allocated object is sequenced before the
\indextext{value computation}%
value computation of the
\grammarterm{new-expression}.

\pnum
If the \grammarterm{new-expression}
creates an array of objects of class type, the destructor is potentially
invoked\iref{class.dtor}.

\pnum
\indextext{\idxcode{new}!exception and}%
If any part of the object initialization described above%
\begin{footnote}
This can
include evaluating a \grammarterm{new-initializer} and/or calling
a constructor.
\end{footnote}
terminates by throwing an exception and a suitable deallocation function
can be found, the deallocation function is called to free the memory in
which the object was being constructed, after which the exception
continues to propagate in the context of the \grammarterm{new-expression}.
If no unambiguous matching deallocation function can be found,
propagating the exception does not cause the object's memory to be
freed.
\begin{note}
This is appropriate when the called allocation function does not
allocate memory; otherwise, it is likely to result in a memory leak.
\end{note}

\pnum
If the \grammarterm{new-expression} does not begin with
a unary \tcode{::} operator and
the allocated type is a class type \tcode{T} or an array thereof,
a search is performed for the deallocation function's name
in the scope of \tcode{T}.
Otherwise, or if nothing is found,
the deallocation function's name is looked up by
searching for it in the global scope.

\pnum
For a non-placement allocation function, the normal deallocation
function lookup is used to find the matching deallocation
function\iref{expr.delete}.
For a placement allocation function, the selection process is described below.
In any case,
the matching deallocation function (if any) shall be non-deleted and
accessible from the point where the \grammarterm{new-expression} appears.

\pnum
For a placement allocation function,
the matching deallocation function is selected as follows:
\begin{itemize}
\item
Each candidate that is a function template is replaced by
the function template specializations (if any)
generated using template argument deduction\iref{temp.over,temp.deduct.call}
with arguments as specified below.
\item
Each candidate whose parameter-type-list is not identical to
that of the allocation function,
ignoring their respective first parameters,
is removed from the set of candidates.
\item
Each candidate whose associated constraints (if any)
are not satisfied\iref{temp.constr.constr}
is removed from the set of candidates.
\item
If exactly one function remains, that function is selected.
\item
Otherwise, no deallocation function is selected.
\end{itemize}
If a usual deallocation function is selected, the program is ill-formed.
\begin{note}
A deallocation function with an additional trailing parameter
compared to the allocation function is never matched,
even if a default argument is provided.
\end{note}

\pnum
\begin{example}
\begin{codeblock}
struct S {
  // Placement allocation function:
  static void* operator new(std::size_t, std::size_t);

  // Usual (non-placement) deallocation function:
  static void operator delete(void*, std::size_t);
};

S* p = new (0) S;   // error: non-placement deallocation function matches
                    // placement allocation function
\end{codeblock}
\end{example}

\begin{example}
\begin{codeblock}
struct A {};
struct T { T(); };

void* operator new(std::size_t s, A& al);       // \#1

template<int = 0>
void operator delete(void* p, A& al);           // \#2

A al;
T* p = new (al) T;                              // OK, uses \#1 and \#2.
\end{codeblock}
\end{example}

\begin{example}
\begin{codeblock}
template<int I>
struct A {};
struct T { T(); };

void* operator new(std::size_t s, A<0>& al);    // \#1

template<int I>
void operator delete(void* p, A<I>& al);
void operator delete(void* p, A<0>& al);

A<0> al;
T* p = new (al) T;      // OK, uses \#1. No deallocation function is selected (two candidates remain).
\end{codeblock}
\end{example}

\begin{example}
\begin{codeblock}
template<int I>
struct A {};
struct T { T(); };

void* operator new(std::size_t s, A<0>& al);    // \#1

template<int I> requires (I > 0)
void operator delete(void* p, A<I>& al);
void operator delete(void* p, A<0>& al);        // \#2

A<0> al;
T* p = new (al) T;                              // OK, uses \#1 and \#2.
\end{codeblock}
\end{example}

\pnum
If a \grammarterm{new-expression} calls a deallocation function, it passes
the value returned from the allocation function call as the first
argument of type \tcode{\keyword{void}*}. If a placement deallocation function is
called, it is passed the same additional arguments as were passed to the
placement allocation function, that is, the same arguments as those
specified with the \grammarterm{new-placement} syntax.
If the implementation is allowed
to introduce a temporary object or make a copy of any argument
as part of the call to the allocation function,
it is unspecified whether the same object is used in the call
to both the allocation and deallocation functions.

\rSec3[expr.delete]{Delete}

\pnum
\indextext{expression!\idxcode{delete}}%
\indextext{\idxcode{delete}}%
The \grammarterm{delete-expression} operator destroys a most derived
object\iref{intro.object} or array created by a
\grammarterm{new-expression}.

\begin{bnf}
\nontermdef{delete-expression}\br
    \opt{\terminal{::}} \keyword{delete} cast-expression\br
    \opt{\terminal{::}} \keyword{delete} \terminal{[} \terminal{]} cast-expression
\end{bnf}

The first alternative is a
\defnx{single-object delete expression}{delete!single-object}, and the
second is an \defnx{array delete expression}{delete!array}.
Whenever the \keyword{delete} keyword is immediately followed by empty square
brackets, it shall be interpreted as the second alternative.
\begin{footnote}
A
\grammarterm{lambda-expression} with a \grammarterm{lambda-introducer}
that consists of empty square brackets can follow the \keyword{delete} keyword
if the \grammarterm{lambda-expression} is enclosed in parentheses.
\end{footnote}
If the operand is of
class type, it is contextually implicitly converted\iref{conv}
to a pointer to object
type
and the converted operand is used in place of the original operand
for the remainder of this subclause.
Otherwise, it shall be a prvalue of pointer to object type.
The \grammarterm{delete-expression} has type
\keyword{void}.

\pnum
\indextext{\idxcode{delete}!single-object}%
In a single-object delete expression, the value of the operand of
\keyword{delete} may be a null pointer value,
a pointer value
that resulted from a previous non-array \grammarterm{new-expression}, or
a pointer to a base class subobject
of an object created by such a \grammarterm{new-expression}.
If not, the behavior is undefined.
\indextext{array!\idxcode{delete}}%
In an array delete expression, the value of the operand of \keyword{delete}
may be a null pointer value or a pointer value that resulted from
a previous array \grammarterm{new-expression} whose
allocation function was not a non-allocating form\iref{new.delete.placement}.
\begin{footnote}
For nonzero-length
arrays, this is the same as a pointer to the first
element of the array created by that \grammarterm{new-expression}.
Zero-length arrays do not have a first element.
\end{footnote}
If not, the behavior is undefined.
\begin{note}
This means that the syntax of the \grammarterm{delete-expression} must
match the type of the object allocated by \keyword{new}, not the syntax of the
\grammarterm{new-expression}.
\end{note}
\begin{note}
A pointer to a \keyword{const} type can be the operand of a
\grammarterm{delete-expression}; it is not necessary to cast away the
constness\iref{expr.const.cast} of the pointer expression before it is
used as the operand of the \grammarterm{delete-expression}.
\end{note}

\pnum
\indextext{\idxcode{delete}!undefined}%
In a single-object delete expression, if the static type of the object to be
deleted is not similar\iref{conv.qual} to its dynamic type
and the selected deallocation function (see below)
is not a destroying operator delete,
the static type shall be a base
class of the dynamic type of the object to be deleted and the static type shall
have a virtual destructor or the behavior is undefined. In an array delete
expression, if the dynamic type of the object to be deleted is not similar to
its static type, the behavior is undefined.

\pnum
\indextext{type!incomplete}%
If the object being deleted has incomplete class type at the point of deletion,
the program is ill-formed.

\pnum
\indextext{\idxcode{delete}!destructor and}%
If the value of the operand of the \grammarterm{delete-expression} is not a
null pointer value
and the selected deallocation function (see below)
is not a destroying operator delete,
evaluating the \grammarterm{delete-expression} invokes the
destructor (if any) for the object or the elements of the array being
deleted.
The destructor shall be accessible from the point where
the \grammarterm{delete-expression} appears.
In the case of an array, the elements are destroyed in
order of decreasing address (that is, in reverse order of the completion
of their constructor; see~\ref{class.base.init}).

\pnum
If the value of the operand of the \grammarterm{delete-expression} is not a
null pointer value, then:

\begin{itemize}
\item
If the allocation call for the \grammarterm{new-expression} for the object to
be deleted was not omitted and the allocation was not extended\iref{expr.new}, the
\grammarterm{delete-expression} shall call a deallocation
function\iref{basic.stc.dynamic.deallocation}. The value returned from the
allocation call of the \grammarterm{new-expression} shall be passed as the
first argument to the deallocation function.

\item
Otherwise, if the allocation was extended or was provided by extending the
allocation of another \grammarterm{new-expression}, and the
\grammarterm{delete-expression} for every other pointer value produced by a
\grammarterm{new-expression} that had storage provided by the extended
\grammarterm{new-expression} has been evaluated, the
\grammarterm{delete-expression} shall call a deallocation function. The value
returned from the allocation call of the extended \grammarterm{new-expression}
shall be passed as the first argument to the deallocation function.

\item
Otherwise, the \grammarterm{delete-expression} will not call a
deallocation function.
\end{itemize}
\begin{note}
The deallocation function is called regardless of whether the destructor
for the object or some element of the array throws an exception.
\end{note}
If the value of the operand of the \grammarterm{delete-expression} is a
null pointer value, it is unspecified whether a deallocation function will be
called as described above.

\pnum
If a deallocation function is called,
it is \tcode{\keyword{operator} \keyword{delete}} for a single-object delete expression or
\tcode{\keyword{operator} \keyword{delete}[]} for an array delete expression.
\begin{note}
\indextext{\idxcode{operator delete}}%
An implementation provides default definitions of the global
deallocation functions\iref{new.delete.single,new.delete.array}.
A \Cpp{} program can provide alternative definitions of these
functions\iref{replacement.functions}, and/or class-specific
versions\iref{class.free}.
\end{note}

\pnum
If the keyword \keyword{delete} in a \grammarterm{delete-expression}
is not preceded by the unary \tcode{::} operator and the type of the operand is
a pointer to a (possibly cv-qualified) class type \tcode{T}
or (possibly multidimensional) array thereof:
\begin{itemize}
\item
For a single-object delete expression,
if the operand is a pointer to \cv{} \tcode{T} and
\tcode{T} has a virtual destructor,
the deallocation function is the one selected at the point of definition of
the dynamic type's virtual destructor\iref{class.dtor}.
\item
Otherwise,
a search is performed for the deallocation function's name
in the scope of \tcode{T}.
\end{itemize}
Otherwise, or if nothing is found,
the deallocation function's name is looked up by
searching for it in the global scope.
In any case, any declarations
other than of usual deallocation functions\iref{basic.stc.dynamic.deallocation}
are discarded.
\begin{note}
If only a placement deallocation function is found in a class,
the program is ill-formed because the lookup set is empty\iref{basic.lookup}.
\end{note}

\pnum
The deallocation function to be called is selected as follows:
\begin{itemize}
\item
If any of the deallocation functions is a destroying operator delete,
all deallocation functions that are not destroying operator deletes
are eliminated from further consideration.
\item
If the type has new-extended alignment,
a function with a parameter of type \tcode{std::align_val_t} is preferred;
otherwise a function without such a parameter is preferred.
If any preferred functions are found,
all non-preferred functions are eliminated from further consideration.
\item
If exactly one function remains,
that function is selected and the selection process terminates.
\item
If the deallocation functions belong to a class scope,
the one without a parameter of type \tcode{std::size_t} is selected.
\item
If the type is complete
and if, for an array delete expression only,
the operand is a pointer to a class type with a
non-trivial destructor or a (possibly multidimensional) array thereof,
the function with a parameter of type \tcode{std::size_t} is selected.
\item
Otherwise, it is unspecified
whether a deallocation function with a parameter of type \tcode{std::size_t}
is selected.
\end{itemize}
Unless the deallocation function is selected
at the point of definition of the dynamic type's virtual destructor,
the selected deallocation function shall be accessible
from the point where the \grammarterm{delete-expression} appears.

\pnum
For a single-object delete expression,
the deleted object is
the object $A$ pointed to by the operand
if the static type of $A$ does not have a virtual destructor,
and the most-derived object of $A$ otherwise.
\begin{note}
If the deallocation function is not a destroying operator delete
and the deleted object is not the most derived object in the former case,
the behavior is undefined,
as stated above.
\end{note}
For an array delete expression,
the deleted object is
the array object.
When a \grammarterm{delete-expression}
is executed, the selected deallocation function shall be called with
the address of the deleted object
in a single-object delete expression, or
the address of the deleted object
suitably adjusted for the array allocation
overhead\iref{expr.new} in an array delete expression,
as its first argument.
\begin{note}
Any cv-qualifiers in the type of the deleted object
are ignored when forming this argument.
\end{note}
If a destroying operator delete is used,
an unspecified value
is passed as the argument
corresponding to the parameter of type \tcode{std::destroying_delete_t}.
If a deallocation function
with a parameter of type \tcode{std::align_val_t}
is used,
the alignment of the type of the deleted object
is passed as the corresponding argument.
If a deallocation function
with a parameter of type \tcode{std::size_t} is used,
the size of the deleted object
in a single-object delete expression, or
of the array plus allocation overhead
in an array delete expression,
is passed as the corresponding argument.
\begin{note}
If this results in a call to a replaceable deallocation function,
and either
the first argument was not the result of
a prior call to a replaceable allocation function or
the second or third argument was not the corresponding argument in said call,
the behavior is undefined\iref{new.delete.single,new.delete.array}.
\end{note}

\rSec3[expr.reflect]{The reflection operator}

\begin{bnf}
\nontermdef{reflect-expression}\br
    \terminal{\caret\caret} \terminal{::}\br
    \terminal{\caret\caret} reflection-name\br
    \terminal{\caret\caret} type-id\br
    \terminal{\caret\caret} id-expression
\end{bnf}

\begin{bnf}
\nontermdef{reflection-name}\br
    \opt{nested-name-specifier} identifier\br
    nested-name-specifier \keyword{template} identifier
\end{bnf}

\pnum
The unary \tcode{\caret\caret} operator,
called the \defnadj{reflection}{operator},
yields a prvalue of type \tcode{std::meta::info}\iref{basic.fundamental}.
\begin{note}
This document places no restriction on representing, by reflections,
constructs not described by this document or
using the names of such constructs
as operands of \grammarterm{reflect-expression}s.
\end{note}

\pnum
The component names of a \grammarterm{reflection-name}
are those of its \grammarterm{nested-name-specifier} (if any) and
its \grammarterm{identifier}.
The terminal name of a \grammarterm{reflection-name} of the form
\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier}
shall denote a template.

\pnum
A \grammarterm{reflect-expression} is parsed as
the longest possible sequence of tokens
that could syntactically form a \grammarterm{reflect-expression}.
An unparenthesized \grammarterm{reflect-expression}
that represents a template shall not be followed by \tcode{<}.
\begin{example}
\begin{codeblock}
static_assert(std::meta::is_type(^^int()));     // \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int()}

template<bool> struct X {};
consteval bool operator<(std::meta::info, X<false>) { return false; }
consteval void g(std::meta::info r, X<false> xv) {
  r == ^^int && true;       // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&\&}
  r == ^^int & true;        // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&}
  r == (^^int) && true;     // OK
  r == ^^int &&&& true;     // error: \tcode{int \&\&\&\&} is not a valid \grammarterm{type-id}
  ^^X < xv;                 // error: \grammarterm{reflect-expression} that represents a template is followed by \tcode{<}
  (^^X) < xv;               // OK
  ^^X<true> < xv;           // OK
}
\end{codeblock}
\end{example}

\pnum
A \grammarterm{reflect-expression} of the form \tcode{\caret\caret ::}
represents the global namespace.

\pnum
If a \grammarterm{reflect-expression} $R$ matches
the form \tcode{\caret\caret \grammarterm{reflection-name}},
it is interpreted as such;
the \grammarterm{identifier} is looked up and
the representation of $R$ is determined as follows:
\begin{itemize}
\item
If lookup finds a declaration
that replaced a \grammarterm{using-declarator}
during a single search\iref{basic.lookup.general,namespace.udecl},
$R$ is ill-formed.
\begin{example}
\begin{codeblock}
struct A { struct S {}; };
struct B : A { using A::S; };
constexpr std::meta::info r1 = ^^B::S;  // error: \tcode{A::S} found through \grammarterm{using-declarator}

struct C : virtual B { struct S {}; };
struct D : virtual B, C {};
D::S s;                                 // OK, names \tcode{C::S} per \ref{class.member.lookup}
constexpr std::meta::info r2 = ^^D::S;  // OK, result \tcode{C::S} not found through \grammarterm{using-declarator}
\end{codeblock}
\end{example}
\item
Otherwise, if lookup finds a namespace alias\iref{namespace.alias},
$R$ represents that namespace alias.
\item
Otherwise, if lookup finds a namespace\iref{basic.namespace},
$R$ represents that namespace.
\item
Otherwise, if lookup finds a concept\iref{temp.concept},
$R$ represents the denoted concept.
\item
Otherwise, if lookup finds a template\iref{temp.names},
the representation of $R$ is determined as follows:
\begin{itemize}
\item
If lookup finds an injected-class-name\iref{class.pre}, then:
\begin{itemize}
\item
If the \grammarterm{reflection-name} is of the form
\tcode{\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier}},
then $R$ represents the class template named by the injected-class-name.
\item
Otherwise, the injected-class-name shall be unambiguous
when considered as a \grammarterm{type-name} and
$R$ represents the class template specialization so named.
\end{itemize}
\item
Otherwise, if lookup finds an overload set,
that overload set shall contain only
declarations of a unique function template F;
$R$ represents F.
\item
Otherwise, if lookup finds
a class template, variable template, or alias template,
$R$ represents that template.
\begin{note}
Lookup never finds a partial or explicit specialization.
\end{note}
\end{itemize}
\item
Otherwise, if lookup finds a type alias $A$,
$R$ represents the underlying entity of $A$
if $A$ was introduced by the declaration of a template parameter;
otherwise, $R$ represents $A$.
\item
Otherwise, if lookup finds a class or an enumeration,
$R$ represents the denoted type.
\item
Otherwise, if lookup finds a class member of an anonymous union\iref{class.union.anon}, $R$ represents that class member.
\item
Otherwise,
the \grammarterm{reflection-name} shall be an \grammarterm{id-expression} \tcode{I}
and $R$ is \tcode{\caret\caret I} (see below).
\end{itemize}

\pnum
A \grammarterm{reflect-expression} $R$ of the form
\tcode{\caret\caret \grammarterm{type-id}}
represents an entity determined as follows:
\begin{itemize}
\item
If the \grammarterm{type-id} designates
a placeholder type\iref{dcl.spec.auto.general},
$R$ is ill-formed.
\item
Otherwise, if the \grammarterm{type-id} is of the form
\opt{\grammarterm{nested-name-specifier}} \opt{\keyword{template}} \grammarterm{simple-template-id}
and whose terminal name is a \grammarterm{template-name}
that names an alias template\iref{temp.alias},
$R$ represents the type alias so named.
\item
Otherwise, $R$ represents the type denoted by the \grammarterm{type-id}.
\end{itemize}

\pnum
A \grammarterm{reflect-expression} $R$ of the form
\tcode{\caret\caret \grammarterm{id-expression}}
represents an entity determined as follows:
\begin{itemize}
\item
If the \grammarterm{id-expression} denotes
\begin{itemize}
\item
a variable declared by
an \grammarterm{init-capture}\iref{expr.prim.lambda.capture},
\item
a function-local predefined variable\iref{dcl.fct.def.general},
\item
a local parameter introduced by
a \grammarterm{requires-expression}\iref{expr.prim.req}, or
\item
a local entity $E$\iref{basic.pre} for which a lambda scope intervenes
between the point at which $E$ was introduced and $R$,
\end{itemize}
then $R$ is ill-formed.
\item
Otherwise, if the \grammarterm{id-expression} denotes an overload set $S$,
overload resolution for the expression \tcode{\&S} with no target
shall select a unique function\iref{over.over};
$R$ represents that function.
\item
Otherwise, if the \grammarterm{id-expression} denotes
a variable, structured binding, enumerator, or non-static data member,
$R$ represents that entity.
\item
Otherwise, $R$ is ill-formed.
\begin{note}
This includes \grammarterm{unqualified-id}s
that name a constant template parameter and
\grammarterm{pack-index-expression}s.
\end{note}
\end{itemize}
The \grammarterm{id-expression} of
a \grammarterm{reflect-expression} is an unevaluated operand\iref{expr.context}.
\begin{example}
\begin{codeblock}
template<typename T> void fn() requires (^^T != ^^int);
template<typename T> void fn() requires (^^T == ^^int);
template<typename T> void fn() requires (sizeof(T) == sizeof(int));

constexpr std::meta::info a = ^^fn<char>;       // OK
constexpr std::meta::info b = ^^fn<int>;        // error: ambiguous

constexpr std::meta::info c = ^^std::vector;    // OK

template<typename T>
struct S {
  static constexpr std::meta::info r = ^^T;
  using type = T;
};
static_assert(S<int>::r == ^^int);
static_assert(^^S<int>::type != ^^int);

typedef struct X {} Y;
typedef struct Z {} Z;
constexpr std::meta::info e = ^^Y;              // OK, represents the type alias \tcode{Y}
constexpr std::meta::info f = ^^Z;              // OK, represents the type alias \tcode{Z}, not the type\iref{basic.lookup.general}
\end{codeblock}
\end{example}

\rSec2[expr.cast]{Explicit type conversion (cast notation)}%
\indextext{expression!cast|(}

\pnum
The result of the expression \tcode{(T)} \grammarterm{cast-expression} is
of type \tcode{T}. The result is an lvalue if \tcode{T} is an lvalue
reference type or an rvalue reference to function type and an xvalue if \tcode{T}
is an rvalue reference to object type; otherwise the result is a prvalue.
\begin{note}
If \tcode{T} is a non-class type that is cv-qualified, the
\grammarterm{cv-qualifier}{s} are discarded when determining the type of the
resulting prvalue; see \ref{expr.prop}.
\end{note}

\pnum
An explicit type conversion can be expressed using functional
notation\iref{expr.type.conv}, a type conversion operator
(\keyword{dynamic_cast}, \keyword{static_cast}, \keyword{reinterpret_cast},
\keyword{const_cast}), or the \term{cast} notation.

\begin{bnf}
\nontermdef{cast-expression}\br
    unary-expression\br
    \terminal{(} type-id \terminal{)} cast-expression
\end{bnf}

\pnum
Any type conversion not mentioned below and not explicitly defined by
the user\iref{class.conv} is ill-formed.

\pnum
The conversions performed by
\begin{itemize}
\indextext{cast!const}%
\indextext{cast!static}%
\indextext{cast!reinterpret}%
\item a \keyword{const_cast}\iref{expr.const.cast},
\item a \keyword{static_cast}\iref{expr.static.cast},
\item a \keyword{static_cast} followed by a \keyword{const_cast},
\item a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}, or
\item a \keyword{reinterpret_cast} followed by a \keyword{const_cast},
\end{itemize}
can be performed using the cast notation of explicit type conversion.
The same semantic restrictions and behaviors apply, with the exception
that in performing a \keyword{static_cast} in the following situations the
conversion is valid even if the base class is inaccessible:
\begin{itemize}
\item a pointer to an object of derived class type or an lvalue or
rvalue of derived class type may be explicitly converted to a pointer or
reference to an unambiguous base class type, respectively;

\item a pointer to member of derived class type may be explicitly
converted to a pointer to member of an unambiguous non-virtual base
class type;

\item a pointer to an object of an unambiguous non-virtual base class
type, a glvalue of an unambiguous non-virtual base class type,
or a pointer to member of an unambiguous non-virtual base class type may
be explicitly converted to a pointer, a reference, or a pointer to
member of a derived class type, respectively.
\end{itemize}

If a conversion can be interpreted in more than one of the ways listed
above, the interpretation that appears first in the list is used, even
if a cast resulting from that interpretation is ill-formed. If a
\keyword{static_cast} followed by a \keyword{const_cast} is used and
the conversion can be interpreted in more than one way as such,
the conversion is
ill-formed.
\begin{example}
\begin{codeblock}
struct A { };
struct I1 : A { };
struct I2 : A { };
struct D : I1, I2 { };
A* foo( D* p ) {
  return (A*)( p );             // ill-formed \keyword{static_cast} interpretation
}

int*** ptr = 0;
auto t = (int const*const*const*)ptr;   // OK, \keyword{const_cast} interpretation

struct S {
  operator const int*();
  operator volatile int*();
};
int *p = (int*)S();     // error: two possible interpretations using \keyword{static_cast} followed by \keyword{const_cast}
\end{codeblock}
\end{example}

\pnum
\indextext{class!cast to incomplete}%
The operand of a cast using the cast notation can be a prvalue of type
``pointer to incomplete class type''. The destination type of a cast
using the cast notation can be ``pointer to incomplete class type''. If
both the operand and destination types are class types and one or both
are incomplete, it is unspecified whether the \keyword{static_cast} or the
\keyword{reinterpret_cast} interpretation is used, even if there is an
inheritance relationship between the two classes.
\begin{note}
For example, if the classes were defined later in the translation unit,
a multi-pass compiler could validly interpret a cast between
pointers to the classes as if the class types were complete at the point
of the cast.
\end{note}
\indextext{expression!cast|)}

\rSec2[expr.mptr.oper]{Pointer-to-member operators}

\pnum
\indextext{expression!pointer-to-member}%
\indextext{pointer to member}%
\indextext{operator!pointer to member}%
\indextext{\idxcode{.*}|see{operator, pointer to member}}%
\indextext{operator!pointer to member}%
\indextext{\idxcode{->*}|see{operator, pointer to member}}%
The pointer-to-member operators \tcode{->*} and \tcode{.*} group
left-to-right.

\begin{bnf}
\nontermdef{pm-expression}\br
    cast-expression\br
    pm-expression \terminal{.*} cast-expression\br
    pm-expression \terminal{->*} cast-expression
\end{bnf}

\pnum
The binary operator \tcode{.*} binds its second operand, which shall be
a prvalue
of type ``pointer to member of \tcode{T}'' to its first operand, which shall be
a glvalue
of
class \tcode{T} or of a class of which \tcode{T} is an unambiguous and
accessible base class. The result is an object or a function of the type
specified by the second operand.

\pnum
The binary operator \tcode{->*} binds its second operand, which shall be
a prvalue
of type ``pointer to member of \tcode{T}'' to its first operand, which shall be of
type ``pointer to \tcode{U}''
where \tcode{U} is either \tcode{T} or
a class of which \tcode{T}
is an unambiguous and accessible base class.
The expression \tcode{E1->*E2} is converted into the equivalent form
\tcode{(*(E1)).*E2}.

\pnum
Abbreviating \grammarterm{pm-expression}\tcode{.*}\grammarterm{cast-expression} as \tcode{E1.*E2}, \tcode{E1}
is called the \defn{object expression}.
If the result of \tcode{E1} is an object
whose type is not similar to the type of \tcode{E1}, or
whose most derived object does not
contain the member to which
\tcode{E2} refers, the behavior is undefined.
The expression \tcode{E1} is sequenced before the expression \tcode{E2}.

\pnum
The restrictions on cv-qualification, and the manner in which
the cv-qualifiers of the operands are combined to produce the
cv-qualifiers of the result, are the same as the rules for
\tcode{E1.E2} given in~\ref{expr.ref}.
\begin{note}
It is not possible to use a pointer to member that refers to a
\keyword{mutable} member to modify a const class object. For
example,
\begin{codeblock}
struct S {
  S() : i(0) { }
  mutable int i;
};
void f()
{
  const S cs;
  int S::* pm = &S::i;          // \tcode{pm} refers to \keyword{mutable} member \tcode{S::i}
  cs.*pm = 88;                  // error: \tcode{cs} is a const object
}
\end{codeblock}
\end{note}

\pnum
\indextext{function!pointer to member}%
If the result of \tcode{.*} or \tcode{->*} is a function, then that
result can be used only as the operand for the function call operator
\tcode{()}.
\begin{example}
\begin{codeblock}
(ptr_to_obj->*ptr_to_mfct)(10);
\end{codeblock}
calls the member function denoted by \tcode{ptr_to_mfct} for the object
pointed to by \tcode{ptr_to_obj}.
\end{example}
In a \tcode{.*} expression whose object expression is an rvalue, the program is
ill-formed if the second operand is a pointer to member function
whose \grammarterm{ref-qualifier} is \tcode{\&},
unless its \grammarterm{cv-qualifier-seq} is \keyword{const}.
In a \tcode{.*}
expression whose object expression is an lvalue, the program is ill-formed if the second
operand is
a pointer to member function
whose \grammarterm{ref-qualifier} is \tcode{\&\&}.
The result of a \tcode{.*} expression
whose second operand is a pointer to a data member is an lvalue if the first
operand is an lvalue and an xvalue otherwise. The result of a \tcode{.*} expression whose
second operand is a pointer to a member function is a prvalue.
If the second operand is the null
member pointer value\iref{conv.mem}, the behavior is undefined.

\rSec2[expr.mul]{Multiplicative operators}%
\indextext{expression!multiplicative operators}%
\indextext{operator!multiplicative}

\pnum
The multiplicative operators \tcode{*}, \tcode{/}, and \tcode{\%} group
left-to-right.

\indextext{operator!multiplication}%
\indextext{\idxcode{*}|see{operator, multiplication}}%
\indextext{operator!division}%
\indextext{\idxcode{/}|see{operator, division}}%
\indextext{operator!remainder}%
\indextext{\idxcode{\%}|see{operator, remainder}}%
\indextext{remainder operator|see{operator, remainder}}%
%
\begin{bnf}
\nontermdef{multiplicative-expression}\br
    pm-expression\br
    multiplicative-expression \terminal{*} pm-expression\br
    multiplicative-expression \terminal{/} pm-expression\br
    multiplicative-expression \terminal{\%} pm-expression
\end{bnf}

\pnum
The operands of \tcode{*} and \tcode{/} shall have arithmetic or unscoped
enumeration type; the operands of \tcode{\%} shall have integral or unscoped
enumeration type. The usual arithmetic conversions\iref{expr.arith.conv} are performed on the
operands and determine the type of the result.

\pnum
The binary \tcode{*} operator indicates multiplication.

\pnum
The binary \tcode{/} operator yields the quotient, and the binary
\tcode{\%} operator yields the remainder from the division of the first
expression by the second.
\indextext{zero!undefined division by}%
If the second operand of \tcode{/} or \tcode{\%} is zero, the behavior is
undefined.
For integral operands, the \tcode{/} operator yields the algebraic quotient with
any fractional part discarded;
\begin{footnote}
This is often called truncation towards zero.
\end{footnote}
if the quotient \tcode{a/b} is representable in the type of the result,
\tcode{(a/b)*b + a\%b} is equal to \tcode{a}; otherwise, the behavior
of both \tcode{a/b} and \tcode{a\%b} is undefined.

\rSec2[expr.add]{Additive operators}%
\indextext{expression!additive operators}%
\indextext{operator!additive}

\pnum
The additive operators \tcode{+} and \tcode{-} group left-to-right.
Each operand shall be a prvalue.
If both operands have arithmetic or unscoped enumeration type,
the usual arithmetic conversions\iref{expr.arith.conv} are performed.
Otherwise, if one operand has arithmetic or unscoped enumeration type,
integral promotion is applied\iref{conv.prom} to that operand.
A converted or promoted operand is used in place of
the corresponding original operand for the remainder of this section.

\indextext{operator!addition}%
\indextext{addition operator|see{operator, addition}}%
\indextext{\idxcode{+}|see{operator, addition}}%
\indextext{operator!subtraction}%
\indextext{subtraction operator|see{operator, subtraction}}%
\indextext{\idxcode{-}|see{operator, subtraction}}%
%
\begin{bnf}
\nontermdef{additive-expression}\br
    multiplicative-expression\br
    additive-expression \terminal{+} multiplicative-expression\br
    additive-expression \terminal{-} multiplicative-expression
\end{bnf}

\indextext{incomplete}%
For addition, either both operands shall have arithmetic
type, or one operand shall be a pointer to a completely-defined object
type and the other shall have integral type.

\pnum
For subtraction, one of the following shall hold:
\begin{itemize}
\item both operands have arithmetic type; or

\item
\indextext{arithmetic!pointer}%
both operands are pointers to cv-qualified or cv-unqualified
versions of the same completely-defined object type; or

\item the left operand is a pointer to a completely-defined object type
and the right operand has integral type.
\end{itemize}

\pnum
The result of the binary \tcode{+} operator is the sum of the operands.
The result of the binary \tcode{-} operator is the difference resulting
from the subtraction of the second operand from the first.

\pnum
\indextext{arithmetic!pointer}%
When an expression \tcode{J} that has integral type
is added to or subtracted from an expression \tcode{P} of pointer type,
the result has the type of \tcode{P}.
\begin{itemize}
\item If \tcode{P} evaluates to a null pointer value and
\tcode{J} evaluates to 0, the result is a null pointer value.
\item Otherwise, if \tcode{P} points to a (possibly-hypothetical) array element $i$
of an array object \tcode{x} with $n$ elements\iref{dcl.array},
\begin{footnote}
As specified in \ref{basic.compound},
an object that is not an array element
is considered to belong to a single-element array for this purpose and
a pointer past the last element of an array of $n$ elements
is considered to be equivalent to a pointer to a hypothetical array element
$n$ for this purpose.
\end{footnote}
the expressions \tcode{P + J} and \tcode{J + P}
(where \tcode{J} has the value $j$)
point to the (possibly-hypothetical) array element
$i + j$ of \tcode{x} if $0 \le i + j \le n$
and the expression \tcode{P - J}
points to the (possibly-hypothetical) array element
$i - j$ of \tcode{x} if $0 \le i - j \le n$.
\item Otherwise, the behavior is undefined.
\end{itemize}
\begin{note}
Adding a value other than $0$ or $1$
to a pointer to a base class subobject, a member subobject,
or a complete object results in undefined behavior.
\end{note}

\pnum
\indextext{\idxcode{ptrdiff_t}}%
\indextext{comparison!undefined pointer}%
The result of subtracting two pointer expressions \tcode{P} and \tcode{Q}
is a prvalue of type \tcode{std::ptrdiff_t}\iref{support.types.layout}.
\begin{itemize}
\item If \tcode{P} and \tcode{Q} both evaluate to null pointer values,
the value is 0.
\item Otherwise, if \tcode{P} and \tcode{Q} point to, respectively,
array elements $i$ and $j$
of the same array object \tcode{x},
the expression \tcode{P - Q} has the value $i - j$.
\begin{note}
If the value $i - j$
is not in the range of representable values
of type \tcode{std::ptrdiff_t},
the behavior is undefined\iref{expr.pre}.
\end{note}
\item Otherwise, the behavior is undefined.
\end{itemize}

\pnum
For addition or subtraction, if the expressions \tcode{P} or \tcode{Q} have
type ``pointer to \cv{}~\tcode{T}'', where \tcode{T} and the array element type
are not similar\iref{conv.qual}, the behavior is undefined.
\begin{example}
\begin{codeblock}
int arr[5] = {1, 2, 3, 4, 5};
unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);
unsigned int k = *p;            // OK, value of \tcode{k} is $2$\iref{conv.lval}
unsigned int *q = p + 1;        // undefined behavior: \tcode{p} points to an \tcode{int}, not an \tcode{unsigned int} object
\end{codeblock}
\end{example}

\rSec2[expr.shift]{Shift operators}

\pnum
\indextext{expression!left-shift-operator}%
\indextext{expression!right-shift-operator}%
\indextext{shift operator!left|see{operator, left shift}}%
\indextext{shift operator!right|see{operator, right shift}}%
\indextext{right shift operator|see{operator, right shift}}%
\indextext{left shift operator|see{operator, left shift}}%
The shift operators \tcode{<<} and \tcode{>>} group left-to-right.

\indextext{operator!left shift}%
\indextext{\idxcode{<<}|see{operator, left shift}}%
\indextext{operator!right shift}%
\indextext{\idxcode{>>}|see{operator, right shift}}%
%
\begin{bnf}
\nontermdef{shift-expression}\br
    additive-expression\br
    shift-expression \terminal{<<} additive-expression\br
    shift-expression \terminal{>>} additive-expression
\end{bnf}

The operands shall be prvalues of integral or unscoped enumeration type and integral
promotions are performed. The type of the result is that of the promoted
left operand.
\indextext{left shift!undefined}%
The behavior is undefined if the right operand is negative, or greater
than or equal to the width of the promoted left operand.

\pnum
The value of \tcode{E1 << E2} is the unique value congruent to
$\tcode{E1} \times 2^\tcode{E2}$ modulo $2^N$,
where $N$ is the width of the type of the result.
\begin{note}
\tcode{E1} is left-shifted \tcode{E2} bit positions;
vacated bits are zero-filled.
\end{note}

\pnum
The value of \tcode{E1 >> E2} is $\tcode{E1} / 2^\tcode{E2}$,
rounded towards negative infinity.
\begin{note}
\tcode{E1} is right-shifted \tcode{E2} bit positions.
Right-shift on signed integral types is an arithmetic right shift,
which performs sign-extension.
\end{note}

\pnum
The expression \tcode{E1} is sequenced before the expression \tcode{E2}.

\rSec2[expr.spaceship]{Three-way comparison operator}
\indextext{expression!three-way comparison}%
\indextext{expression!spaceship}%

\pnum
The three-way comparison operator groups left-to-right.

\indextext{\idxcode{<=>}|see{operator, three-way comparison}}%
\indextext{operator!three-way comparison}%
\indextext{operator!spaceship}%

\begin{bnf}
\nontermdef{compare-expression}\br
    shift-expression\br
    compare-expression \terminal{<=>} shift-expression
\end{bnf}

\pnum
The expression \tcode{p <=> q} is a prvalue indicating whether
\tcode{p} is less than, equal to, greater than, or incomparable with
\tcode{q}.

\pnum
If one of the operands is of type \keyword{bool}
and the other is not, the program is ill-formed.

\pnum
If both operands have arithmetic types,
or one operand has integral type and
the other operand has unscoped enumeration type,
the usual arithmetic conversions\iref{expr.arith.conv} are applied to the operands.
Then:

\begin{itemize}
\item
If a narrowing conversion\iref{dcl.init.list} is required,
other than from an integral type to a floating-point type,
the program is ill-formed.

\item
Otherwise, if the operands have integral type,
the result is of type \tcode{std::strong_ordering}.
The result is
\tcode{std::strong_ordering::equal}
if both operands are arithmetically equal,
\tcode{std::strong_ordering::less}
if the first operand is arithmetically
less than the second operand,
and
\tcode{std::strong_ordering::greater}
otherwise.
\item
Otherwise, the operands have floating-point type, and
the result is of type \tcode{std::partial_ordering}.
The expression \tcode{a <=> b} yields
\tcode{std::partial_ordering::less}
if \tcode{a} is less than \tcode{b},
\tcode{std::partial_ordering::greater}
if \tcode{a} is greater than \tcode{b},
\tcode{std::partial_ordering::equivalent}
if \tcode{a} is equivalent to \tcode{b},
and
\tcode{std::partial_ordering::unordered} otherwise.
\end{itemize}

\pnum
If both operands have the same enumeration type \tcode{E},
the operator yields the result of
converting the operands to the underlying type of \tcode{E}
and applying \tcode{<=>} to the converted operands.

\pnum
If at least one of the operands is of object pointer type and
the other operand is of object pointer or array type,
array-to-pointer conversions\iref{conv.array},
pointer conversions\iref{conv.ptr},
and
qualification conversions\iref{conv.qual}
are performed on both operands
to bring them to their composite pointer type\iref{expr.type}.
After the conversions, the operands shall have the same type.
\begin{note}
If both of the operands are arrays,
array-to-pointer conversions\iref{conv.array} are not applied.
\end{note}
In this case,
\tcode{p <=> q} is of type \tcode{std::strong_ordering} and
the result is defined by the following rules:
\begin{itemize}
\item
If two pointer operands \tcode{p} and \tcode{q} compare equal\iref{expr.eq},
\tcode{p <=> q} yields \tcode{std::strong_ordering::equal};
\item
otherwise, if \tcode{p} and \tcode{q} compare unequal,
\tcode{p <=> q} yields
\tcode{std::strong_ordering::less}
if \tcode{q} compares greater than \tcode{p}
and
\tcode{std::strong_ordering::greater}
if \tcode{p} compares greater than \tcode{q}\iref{expr.rel};
\item
otherwise, the result is unspecified.
\end{itemize}

\pnum
Otherwise, the program is ill-formed.

\pnum
The three comparison category types\iref{cmp.categories}
(the types
\tcode{std::strong_ordering},
\tcode{std::weak_ordering}, and
\tcode{std::partial_ordering})
are not predefined;
if a standard library declaration\iref{compare.syn,std.modules}
of such a class type does not precede\iref{basic.lookup.general}
a use of that type ---
even an implicit use in which the type is not named
(e.g., via the \keyword{auto} specifier\iref{dcl.spec.auto}
in a defaulted three-way comparison\iref{class.spaceship}
or use of the built-in operator) --- the program is ill-formed.

\rSec2[expr.rel]{Relational operators}%
\indextext{expression!relational operators}%
\indextext{operator!relational}

\pnum
The relational operators group left-to-right.
\begin{example}
\tcode{a<b<c} means \tcode{(a<b)<c} and \emph{not}
\tcode{(a<b)\&\&(b<c)}.
\end{example}
\indextext{operator!less than}%
\indextext{\idxcode{<}|see{operator, less than}}%
\indextext{operator!greater than}%
\indextext{\idxcode{>}|see{operator, greater than}}%
\indextext{operator!less than or equal to}%
\indextext{\idxcode{<=}|see{operator, less than or equal to}}%
\indextext{operator!greater than or equal to}%
\indextext{\idxcode{>=}|see{operator, greater than or equal to}}%
%
\begin{bnf}
\nontermdef{relational-expression}\br
    compare-expression\br
    relational-expression \terminal{<} compare-expression\br
    relational-expression \terminal{>} compare-expression\br
    relational-expression \terminal{<=} compare-expression\br
    relational-expression \terminal{>=} compare-expression
\end{bnf}
%
The
lvalue-to-rvalue\iref{conv.lval}
and function-to-pointer\iref{conv.func}
standard conversions are performed on the operands.
If one of the operands is a pointer, the
array-to-pointer conversion\iref{conv.array} is performed on the other operand.

\pnum
The converted operands shall have arithmetic, enumeration, or pointer type.
The
operators \tcode{<} (less than), \tcode{>} (greater than), \tcode{<=}
(less than or equal to), and \tcode{>=} (greater than or equal to) all
yield \keyword{false} or \keyword{true}. The type of the result is
\keyword{bool}.

\pnum
The usual arithmetic conversions\iref{expr.arith.conv} are performed on operands of arithmetic
or enumeration type. If both converted operands are pointers,
pointer conversions\iref{conv.ptr},
function pointer conversions\iref{conv.fctptr}, and
qualification conversions\iref{conv.qual}
are performed to bring
them to their composite pointer type\iref{expr.type}.
After conversions, the operands shall have the same type.

\pnum
The result of comparing unequal pointers to objects
\begin{footnote}
As specified in \ref{basic.compound},
an object that is not an array element
is considered to belong to a
single-element array for this purpose and
a pointer past the last element of an array of $n$ elements
is considered to be equivalent to a pointer to a hypothetical array element
$n$ for this purpose.
\end{footnote}
is defined in terms of a partial order consistent with the following rules:

\begin{itemize}
\item If two pointers point to different elements of the same array, or to
subobjects thereof, the pointer to the element with the higher subscript
is required to compare greater.

\item If two pointers point to different non-static data members of the same
object, or to subobjects of such members, recursively,
the pointer to the later declared member is required to compare greater provided
neither member is a subobject of zero size
and their class is not a union.

\item Otherwise, neither pointer is required to compare greater than the other.

\end{itemize}

\pnum
If two operands \tcode{p} and \tcode{q} compare equal\iref{expr.eq},
\tcode{p<=q} and \tcode{p>=q} both yield \keyword{true} and \tcode{p<q} and
\tcode{p>q} both yield \keyword{false}. Otherwise, if a pointer to object \tcode{p}
compares greater than a pointer \tcode{q}, \tcode{p>=q}, \tcode{p>q},
\tcode{q<=p}, and \tcode{q<p} all yield \keyword{true} and \tcode{p<=q},
\tcode{p<q}, \tcode{q>=p}, and \tcode{q>p} all yield \keyword{false}.
Otherwise, the result of each of the operators is unspecified.
\begin{note}
A relational operator applied
to unequal function pointers
yields an unspecified result.
A pointer value of type ``pointer to \cv{}~\keyword{void}''
can point to an object\iref{basic.compound}.
\end{note}

\pnum
If both operands (after conversions) are of arithmetic or enumeration type, each
of the operators shall yield \keyword{true} if the specified relationship is true
and \keyword{false} if it is false.

\rSec2[expr.eq]{Equality operators}%
\indextext{expression!equality operators}%
\indextext{operator!equality}%
\indextext{operator!inequality}

\begin{bnf}
\nontermdef{equality-expression}\br
    relational-expression\br
    equality-expression \terminal{==} relational-expression\br
    equality-expression \terminal{!=} relational-expression
\end{bnf}

\pnum
The \tcode{==} (equal to) and the \tcode{!=} (not equal to) operators
group left-to-right.
The
lvalue-to-rvalue\iref{conv.lval}
and function-to-pointer\iref{conv.func}
standard conversions are performed on the operands.
If one of the operands is a pointer or a null pointer constant\iref{conv.ptr},
the array-to-pointer conversion\iref{conv.array} is performed
on the other operand.

\pnum
The converted operands shall have scalar type. The operators
\tcode{==} and \tcode{!=} both yield \keyword{true} or \keyword{false}, i.e., a
result of type \keyword{bool}. In each case below, the operands shall have the
same type after the specified conversions have been applied.

\pnum
\indextext{comparison!pointer}%
\indextext{comparison!pointer to function}%
If at least one of the converted operands is a pointer,
pointer conversions\iref{conv.ptr},
function pointer conversions\iref{conv.fctptr}, and
qualification conversions\iref{conv.qual}
are performed on both operands to bring them to their composite pointer type\iref{expr.type}.
Comparing pointers is defined as follows:

\begin{itemize}
\item
If one pointer represents the address of a complete object, and another
pointer represents the address one past the last element of a different
complete object,
\begin{footnote}
As specified in \ref{basic.compound},
an object that is not an array element is
considered to belong to a single-element array for this purpose.
\end{footnote}
the result of the comparison is unspecified.
\item
Otherwise, if the pointers are both null, both point to the same
\indextext{address}%
function, or both represent the same address\iref{basic.compound},
they compare equal.
\item
Otherwise, the pointers compare unequal.
\end{itemize}

\pnum
If at least one of the operands is a pointer to member,
pointer-to-member conversions\iref{conv.mem},
function pointer conversions\iref{conv.fctptr}, and
qualification conversions\iref{conv.qual}
are performed on both operands to bring them to
their composite pointer type\iref{expr.type}.
Comparing pointers to members is defined as follows:

\begin{itemize}
\item
If two pointers to members are both the null member pointer value, they compare
equal.

\item
If only one of two pointers to members is the null member pointer value, they
compare unequal.

\item
If either is a pointer to a virtual member function, the result is unspecified.

\item
If one refers to a member of class \tcode{C1} and the other refers to a member
of a different class \tcode{C2}, where neither is a base class of the other,
the result is unspecified.
\begin{example}
\begin{codeblock}
struct A {};
struct B : A { int x; };
struct C : A { int x; };

int A::*bx = (int(A::*))&B::x;
int A::*cx = (int(A::*))&C::x;

bool b1 = (bx == cx);   // unspecified
\end{codeblock}
\end{example}

\item
If both refer to (possibly different) members of the same union\iref{class.union},
they compare equal.

\item
Otherwise, two pointers to members compare equal if they would refer to the same member of
the same most derived object\iref{intro.object} or the same subobject if
indirection with a hypothetical object of the associated
class type were performed, otherwise they compare unequal.
\begin{example}
\begin{codeblock}
struct B {
  int f();
};
struct L : B { };
struct R : B { };
struct D : L, R { };

int (B::*pb)() = &B::f;
int (L::*pl)() = pb;
int (R::*pr)() = pb;
int (D::*pdl)() = pl;
int (D::*pdr)() = pr;
bool x = (pdl == pdr);          // \tcode{false}
bool y = (pb == pl);            // \tcode{true}
\end{codeblock}
\end{example}
\end{itemize}

\pnum
Two operands of type \tcode{std::nullptr_t} or one operand of type
\tcode{std::nullptr_t} and the other a null pointer constant compare equal.

\pnum
If both operands are of type \tcode{std::meta::info},
they compare equal if both operands
\begin{itemize}
\item are null reflection values,
\item represent values that are template-argument-equivalent\iref{temp.type},
\item represent the same object,
\item represent the same entity,
\item represent the same annotation\iref{dcl.attr.annotation},
\item represent the same direct base class relationship, or
\item represent equal data member descriptions\iref{class.mem.general},
\end{itemize}
and they compare unequal otherwise.

\pnum
If two operands compare equal, the result is \keyword{true} for
the \tcode{==} operator and \keyword{false} for the \tcode{!=} operator. If two operands
compare unequal, the result is \keyword{false} for the \tcode{==} operator and
\keyword{true} for the \tcode{!=} operator. Otherwise, the result of each of the
operators is unspecified.

\pnum
If both operands are of arithmetic or enumeration type, the usual arithmetic
conversions\iref{expr.arith.conv} are performed on both operands; each of the operators shall yield
\keyword{true} if the specified relationship is true and \keyword{false} if it is
false.

\rSec2[expr.bit.and]{Bitwise AND operator}%
\indextext{expression!bitwise AND}%
\indextext{operator!bitwise}%
\indextext{operator!bitwise AND}%
\indextext{\idxcode{\&}|see{operator, bitwise AND}}%

\begin{bnf}
\nontermdef{and-expression}\br
    equality-expression\br
    and-expression \terminal{\&} equality-expression
\end{bnf}

\pnum
The \tcode{\&} operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions\iref{expr.arith.conv} are performed.
Given the coefficients $\tcode{x}_i$ and $\tcode{y}_i$
of the base-2 representation\iref{basic.fundamental}
of the converted operands \tcode{x} and \tcode{y},
the coefficient $\tcode{r}_i$
of the base-2 representation of the result \tcode{r}
is 1 if both $\tcode{x}_i$ and $\tcode{y}_i$ are 1, and 0 otherwise.
\begin{note}
The result is the bitwise \logop{and} function of the operands.
\end{note}

\rSec2[expr.xor]{Bitwise exclusive OR operator}%
\indextext{expression!bitwise exclusive OR}%
\indextext{operator!bitwise exclusive OR}%
\indextext{\idxcode{\caret}|see{operator, bitwise exclusive OR}}

\begin{bnf}
\nontermdef{exclusive-or-expression}\br
    and-expression\br
    exclusive-or-expression \terminal{\caret} and-expression
\end{bnf}

\pnum
The \tcode{\caret} operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions\iref{expr.arith.conv} are performed.
Given the coefficients $\tcode{x}_i$ and $\tcode{y}_i$
of the base-2 representation\iref{basic.fundamental}
of the converted operands \tcode{x} and \tcode{y},
the coefficient $\tcode{r}_i$
of the base-2 representation of the result \tcode{r}
is 1 if either (but not both) of $\tcode{x}_i$ and $\tcode{y}_i$ is 1,
and 0 otherwise.
\begin{note}
The result is the bitwise exclusive \logop{or} function of the operands.
\end{note}

\rSec2[expr.or]{Bitwise inclusive OR operator}%
\indextext{expression!bitwise inclusive OR}%
\indextext{operator!bitwise inclusive OR}%
\indextext{\idxcode{"|}|see{operator, bitwise inclusive OR}}

\begin{bnf}
\nontermdef{inclusive-or-expression}\br
    exclusive-or-expression\br
    inclusive-or-expression \terminal{|} exclusive-or-expression
\end{bnf}

\pnum
The \tcode{|} operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions\iref{expr.arith.conv} are performed.
Given the coefficients $\tcode{x}_i$ and $\tcode{y}_i$
of the base-2 representation\iref{basic.fundamental}
of the converted operands \tcode{x} and \tcode{y},
the coefficient $\tcode{r}_i$
of the base-2 representation of the result \tcode{r}
is 1 if at least one of $\tcode{x}_i$ and $\tcode{y}_i$ is 1, and 0 otherwise.
\begin{note}
The result is the bitwise inclusive \logop{or} function of the operands.
\end{note}

\rSec2[expr.log.and]{Logical AND operator}%
\indextext{expression!logical AND}%
\indextext{operator!logical AND}%
\indextext{\idxcode{\&\&}|see{operator, logical AND}}%

\begin{bnf}
\nontermdef{logical-and-expression}\br
    inclusive-or-expression\br
    logical-and-expression \terminal{\&\&} inclusive-or-expression
\end{bnf}

\pnum
The \tcode{\&\&} operator groups left-to-right. The operands are both
contextually converted to \keyword{bool}\iref{conv}.
The
result is \keyword{true} if both operands are \keyword{true} and
\keyword{false} otherwise. Unlike \tcode{\&}, \tcode{\&\&} guarantees
left-to-right evaluation: the second operand is not evaluated if the
first operand is \keyword{false}.

\pnum
The result is a \tcode{bool}.
\indextext{operator!side effects and logical AND}%
If the second expression is evaluated,
the first expression is sequenced before
the second expression\iref{intro.execution}.

\rSec2[expr.log.or]{Logical OR operator}%
\indextext{expression!logical OR}%
\indextext{operator!logical OR}%
\indextext{\idxcode{"|"|}|see{operator, logical OR}}%

\begin{bnf}
\nontermdef{logical-or-expression}\br
    logical-and-expression\br
    logical-or-expression \terminal{||} logical-and-expression
\end{bnf}

\pnum
The \tcode{||} operator groups left-to-right. The operands are both
contextually converted to \keyword{bool}\iref{conv}.
The result is
\keyword{true} if either of its operands is \keyword{true}, and
\keyword{false} otherwise. Unlike \tcode{|}, \tcode{||} guarantees
left-to-right evaluation; moreover, the second operand is not evaluated
if the first operand evaluates to \keyword{true}.

\pnum
The result is a \keyword{bool}.
\indextext{operator!side effects and logical OR}%
If the second expression is evaluated,
the first expression is sequenced before
the second expression\iref{intro.execution}.

\rSec2[expr.cond]{Conditional operator}%
\indextext{expression!conditional operator}%
\indextext{operator!conditional expression}%
\indextext{\idxcode{?:}|see{operator, conditional expression}}%

\begin{bnf}
\nontermdef{conditional-expression}\br
    logical-or-expression\br
    logical-or-expression \terminal{?} expression \terminal{:} assignment-expression
\end{bnf}

\pnum
Conditional expressions group right-to-left. The first expression is
contextually converted to \keyword{bool}\iref{conv}.
It is
evaluated and if it is \keyword{true}, the result of the conditional
expression is the value of the second expression, otherwise that of the
third expression. Only one of the second and third expressions is
evaluated.
The first expression is sequenced before
the second or third expression\iref{intro.execution}.

\pnum
If either the second or the third operand has type \keyword{void},
one of the following shall hold:
\begin{itemize}
\item
\indextext{conditional-expression!throw-expression in}%
The second or the third operand (but not both) is a (possibly
parenthesized) \grammarterm{throw-expression}\iref{expr.throw}; the result
is of the type and value category of the other.
The \grammarterm{conditional-expression}
is a bit-field if that operand is a bit-field.

\item Both the second and the third operands have type \keyword{void}; the
result is of type \keyword{void} and is a prvalue.
\begin{note}
This
includes the case where both operands are \grammarterm{throw-expression}{s}.
\end{note}
\end{itemize}

\pnum
Otherwise, if the second and third operand are glvalue bit-fields
of the same value category and
of types \cvqual{cv1} \tcode{T} and \cvqual{cv2} \tcode{T}, respectively,
the operands are considered to be of type \cv{} \tcode{T}
for the remainder of this subclause,
where \cv{} is the union of \cvqual{cv1} and \cvqual{cv2}.

\pnum
Otherwise, if the second and third operand have different types and
either has (possibly cv-qualified) class type, or if both
are glvalues of the same value category and the same type except for
cv-qualification, an attempt is made to
form an implicit conversion sequence\iref{over.best.ics} from
each of those operands to the type of the other.
\begin{note}
Properties such as access, whether an operand is a bit-field, or whether
a conversion function is deleted are ignored for that determination.
\end{note}
Attempts are made to form an implicit conversion sequence
from an operand expression \tcode{E1} of type \tcode{T1}
to a target type related to the type \tcode{T2}
of the operand expression \tcode{E2} as follows:

\begin{itemize}
\item If \tcode{E2} is an lvalue, the target type is
``lvalue reference to \tcode{T2}'',
but an implicit conversion sequence can only be formed
if the reference would bind directly\iref{dcl.init.ref}
to a glvalue.

\item If \tcode{E2} is an xvalue, the target type is
``rvalue reference to \tcode{T2}'',
but an implicit conversion sequence can only be formed
if the reference would bind directly.

\item If \tcode{E2} is a prvalue or if neither of the conversion sequences above can be
formed and at least one of the operands has (possibly cv-qualified) class type:
\begin{itemize}
\item if \tcode{T1} and \tcode{T2} are the same class type
(ignoring cv-qualification):
  \begin{itemize}
  \item
  if \tcode{T2} is at least as cv-qualified as \tcode{T1},
  the target type is \tcode{T2},
  \item
  otherwise, no conversion sequence is formed for this operand;
  \end{itemize}

\item otherwise, if \tcode{T2} is a base class of \tcode{T1},
the target type is \cvqual{cv1} \tcode{T2}, where \cvqual{cv1}
denotes the cv-qualifiers of \tcode{T1};

\item otherwise, the target type is the type that \tcode{E2} would have
after applying the
lvalue-to-rvalue\iref{conv.lval},
array-to-pointer\iref{conv.array}, and
function-to-pointer\iref{conv.func}
standard conversions.
\end{itemize}
\end{itemize}

Using this process, it is determined whether an implicit conversion
sequence can be formed from the second operand
to the target type determined for the third operand, and vice versa,
with the following outcome:
\begin{itemize}
\item If both sequences can be formed, or one can be formed but it is the
ambiguous conversion sequence, the program is ill-formed.
\item If no conversion sequence can be formed, the operands are left unchanged
and further checking is performed as described below.
\item Otherwise, if exactly one conversion sequence can be formed,
that conversion is applied to the chosen operand
and the converted operand is used in place of the original operand for
the remainder of this subclause.
\begin{note}
The conversion might be ill-formed even if an implicit conversion
sequence could be formed.
\end{note}
\end{itemize}

\pnum
If the second and third operands are glvalues of the same value category
and have the same type, the
result is of that type and value category and it is a bit-field if the
second or the third operand is a bit-field, or if both are bit-fields.

\pnum
Otherwise, the result is a prvalue. If the second and third operands do
not have the same type, and either has (possibly cv-qualified) class
type, overload resolution is used to determine the conversions (if any)
to be applied to the operands\iref{over.match.oper,over.built}.
If the overload resolution fails, the program is ill-formed. Otherwise,
the conversions thus determined are applied, and the converted operands
are used in place of the original operands for the remainder of this
subclause.

\pnum
Array-to-pointer\iref{conv.array}
and function-to-pointer\iref{conv.func} standard conversions are
performed on the second and third operands. After those conversions, one
of the following shall hold:

\begin{itemize}
\item The second and third operands have the same type; the result is of
that type and the result is copy-initialized using the selected operand.

\item The second and third operands have arithmetic or enumeration type;
the usual arithmetic conversions\iref{expr.arith.conv} are performed to bring them to a common
type, and the result is of that type.

\item One or both of the second and third operands have pointer type;
lvalue-to-rvalue\iref{conv.lval},
pointer\iref{conv.ptr},
function pointer\iref{conv.fctptr}, and
qualification conversions\iref{conv.qual}
are performed to bring them to their
composite pointer type\iref{expr.type}. The result is of the composite
pointer type.

\item One or both of the second and third operands have pointer-to-member type;
lvalue-to-rvalue\iref{conv.lval},
pointer to member\iref{conv.mem},
function pointer\iref{conv.fctptr}, and
qualification conversions\iref{conv.qual}
are performed to bring them to their composite
pointer type\iref{expr.type}. The result is of the composite pointer type.

\item
Both the second and third operands have type \tcode{std::nullptr_t} or one has
that type and the other is a null pointer constant. The result is of type
\tcode{std::nullptr_t}.

\end{itemize}

\rSec2[expr.yield]{Yielding a value}%
\indextext{expression!yield}%
\indextext{\idxcode{co_yield}}%

\begin{bnf}
  \nontermdef{yield-expression}\br
  \keyword{co_yield} assignment-expression\br
  \keyword{co_yield} braced-init-list
\end{bnf}

\pnum
A \grammarterm{yield-expression} shall appear only within a suspension context
of a function\iref{expr.await}.
Let \placeholder{e} be the operand of the \grammarterm{yield-expression} and
\placeholder{p} be an lvalue naming the promise object of the enclosing
coroutine\iref{dcl.fct.def.coroutine}, then the \grammarterm{yield-expression}
is equivalent to the expression
\tcode{\keyword{co_await} \placeholder{p}.yield_value(\placeholder{e})}.

\begin{example}
\begin{codeblock}
template <typename T>
struct my_generator {
  struct promise_type {
    T current_value;
    @\commentellip@
    auto yield_value(T v) {
      current_value = std::move(v);
      return std::suspend_always{};
    }
  };
  struct iterator { @\commentellip@ };
  iterator begin();
  iterator end();
};

my_generator<pair<int,int>> g1() {
  for (int i = 0; i < 10; ++i) co_yield {i,i};
}
my_generator<pair<int,int>> g2() {
  for (int i = 0; i < 10; ++i) co_yield make_pair(i,i);
}

auto f(int x = co_yield 5);     // error: \grammarterm{yield-expression} outside of function suspension context
int a[] = { co_yield 1 };       // error: \grammarterm{yield-expression} outside of function suspension context

int main() {
  auto r1 = g1();
  auto r2 = g2();
  assert(std::equal(r1.begin(), r1.end(), r2.begin(), r2.end()));
}
\end{codeblock}
\end{example}

\rSec2[expr.throw]{Throwing an exception}%
\indextext{expression!\idxcode{throw}}%
\indextext{exception handling!throwing}%
\indextext{\idxcode{throw}}%
%
\begin{bnf}
\nontermdef{throw-expression}\br
    \keyword{throw}  \opt{assignment-expression}
\end{bnf}

\pnum
A \grammarterm{throw-expression} is of type \keyword{void}.

\pnum
A \grammarterm{throw-expression} with an operand throws an
exception\iref{except.throw}.
The array-to-pointer\iref{conv.array} and function-to-pointer\iref{conv.func}
standard conversions are performed on the operand.
The type of the exception object is determined by removing
any top-level \grammarterm{cv-qualifier}{s} from the type of the
(possibly converted) operand.
The exception object is copy-initialized\iref{dcl.init.general}
from the (possibly converted) operand.

\pnum
\indextext{exception handling!rethrow}%
A
\grammarterm{throw-expression}
with no operand rethrows the currently handled exception\iref{except.handle}.
\indextext{exception handling!terminate called@\tcode{terminate} called}%
\indextext{\idxcode{terminate}!called}%
If no exception is presently being handled,
the function \tcode{std::terminate} is invoked\iref{except.terminate}.
Otherwise, the exception is reactivated with the existing exception object;
no new exception object is created.
The exception is no longer considered to be caught.
\begin{example}
An exception handler that cannot completely handle the exception itself
can be written like this:
\begin{codeblock}
try {
  // ...
} catch (...) {     // catch all exceptions
  // respond (partially) to exception
  throw;            // pass the exception to some other handler
}
\end{codeblock}
\end{example}

\rSec2[expr.assign]{Assignment and compound assignment operators}%
\indextext{expression!assignment and compound assignment}

\pnum
\indextext{operator!assignment}%
\indextext{\idxcode{=}|see{assignment operator}}%
\indextext{operator!\idxcode{+=}}%
\indextext{operator!\idxcode{-=}}%
\indextext{operator!\idxcode{*=}}%
\indextext{operator!\idxcode{/=}}%
\indextext{operator!\idxcode{\%=}}%
\indextext{operator!\idxcode{>>=}}%
\indextext{operator!\idxcode{<<=}}%
\indextext{operator!\idxcode{\&=}}%
\indextext{operator!\idxcode{\caret=}}%
\indextext{operator!\idxcode{"|=}}%
The assignment operator (\tcode{=}) and the compound assignment
operators all group right-to-left.
\indextext{assignment!and lvalue}%
All
require a modifiable lvalue as their left operand; their result is an lvalue
of the type of the left operand, referring to the left operand. The result in all cases is a bit-field if
the left operand is a bit-field. In all cases, the assignment is
sequenced after the
\indextext{value computation}%
value computation of the right and left operands,
and before the
value computation of the assignment expression.
The right operand is sequenced before the left operand.
With
respect to an indeterminately-sequenced function call, the operation of
a compound assignment is a single evaluation.
\begin{note}
Therefore, a function call cannot intervene between the
lvalue-to-rvalue conversion and the side effect associated with any
single compound assignment operator.
\end{note}

\begin{bnf}
\nontermdef{assignment-expression}\br
    conditional-expression\br
    yield-expression\br
    throw-expression\br
    logical-or-expression assignment-operator initializer-clause
\end{bnf}

\begin{bnf}
\nontermdef{assignment-operator} \textnormal{one of}\br
    \terminal{=  *=  /=  \%=   +=  -=  >>=  <<=  \&=  \caret=  |=}
\end{bnf}

\pnum
In simple assignment (\tcode{=}),
let \tcode{V} be the result of the right operand;
the object referred to by the left operand is
modified\iref{defns.access} by replacing its value
with \tcode{V} or,
if the object is of integer type,
with the value congruent\iref{basic.fundamental} to \tcode{V}.

\pnum
\indextext{assignment!conversion by}%
If the right operand is an expression, it is implicitly
converted\iref{conv} to the cv-unqualified type of the left
operand.

\pnum
\indextext{reference!assignment to}%
When the left operand of an assignment operator
is a bit-field that cannot represent the value of the expression, the
resulting value of the bit-field is
\impldefplain{value of bit-field that cannot represent!assigned value}.

\pnum
An assignment whose left operand is of
a volatile-qualified type is deprecated\iref{depr.volatile.type}
unless the (possibly parenthesized) assignment is a discarded-value expression or
an unevaluated operand\iref{term.unevaluated.operand}.

\pnum
The behavior of an expression of the form \tcode{E1 \placeholder{op}= E2}
is equivalent to \tcode{E1 = E1 \placeholder{op} E2} except
that \tcode{E1} is evaluated only once.
\begin{note}
The object designated by \tcode{E1} is accessed twice.
\end{note}
For \tcode{+=} and \tcode{-=},
\tcode{E1} shall either have arithmetic type or be a pointer to a
possibly cv-qualified completely-defined object type. In all other
cases, \tcode{E1} shall have arithmetic type.

\pnum
If the value being stored in an object is read via another object that
overlaps in any way the storage of the first object, then the overlap shall be
exact and the two objects shall have the same type, otherwise the behavior is
undefined.
\begin{note}
This restriction applies to the relationship
between the left and right sides of the assignment operation; it is not a
statement about how the target of the assignment can be aliased in general.
See~\ref{basic.lval}.
\end{note}

\pnum
A \grammarterm{braced-init-list} $B$ may appear on the right-hand side of

\begin{itemize}
\item
an assignment to a scalar of type \tcode{T}, in which case $B$
shall have at most a single element.
The meaning of \tcode{x = $B$} is \tcode{x = t},
where \tcode{t} is an invented temporary variable
declared and initialized as \tcode{T t = $B$}.

\item
an assignment to an object of class type, in which case $B$
is passed as the argument to the assignment operator function selected by
overload resolution\iref{over.assign,over.match}.
\end{itemize}

\begin{example}
\begin{codeblock}
complex<double> z;
z = { 1,2 };        // meaning \tcode{z.operator=(\{1,2\})}
z += { 1, 2 };      // meaning \tcode{z.operator+=(\{1,2\})}
int a, b;
a = b = { 1 };      // meaning \tcode{a=b=1;}
a = { 1 } = b;      // syntax error
\end{codeblock}
\end{example}

\rSec2[expr.comma]{Comma operator}%
\indextext{expression!comma}%
\indextext{operator!comma}%
\indextext{comma operator|see{operator, comma}}%
\indextext{\idxcode{,}|see{operator, comma}}%
\indextext{sequencing operator|see{operator, comma}}%

\pnum
The comma operator groups left-to-right.

\begin{bnf}
\nontermdef{expression}\br
    assignment-expression\br
    expression \terminal{,} assignment-expression
\end{bnf}

A pair of expressions separated by a comma is evaluated left-to-right;
the left expression is
a discarded-value expression\iref{expr.prop}.
The left expression is sequenced before
the right expression\iref{intro.execution}.
\indextext{operator!side effects and comma}%
The type and value of the
result are the type and value of the right operand; the result is of the same
value category as its right operand, and is a bit-field if its
right operand is a bit-field.

\pnum
\begin{note}
In contexts where the comma token is given special meaning
(e.g., function calls\iref{expr.call},
subscript expressions\iref{expr.sub},
lists of initializers\iref{dcl.init},
or \grammarterm{template-argument-list}{s}\iref{temp.names}),
the comma operator as described in this subclause can appear only in parentheses.
\begin{example}
\begin{codeblock}
f(a, (t=3, t+2), c);
\end{codeblock}
has three arguments, the second of which has the value
\tcode{5}.
\end{example}
\end{note}

\rSec1[expr.const]{Constant evaluation}%
\indextext{expression!constant}

\rSec2[expr.const.general]{General}

\begin{bnf}
\nontermdef{constant-expression}\br
    conditional-expression
\end{bnf}

\pnum
Certain contexts require expressions that satisfy additional
requirements as detailed in \ref{expr.const}; other contexts have different
semantics depending on whether or not an expression satisfies these requirements.
Expressions that satisfy these requirements,
assuming that copy elision\iref{class.copy.elision} is not performed,
are called constant expressions.
\begin{note}
Certain constant expressions are evaluated during translation\iref{lex.phases}.
\end{note}

\pnum
\recommended
Implementations should provide consistent results of floating-point evaluations,
irrespective of whether the evaluation is performed
during translation or during program execution.
\begin{note}
Since this document
imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the
evaluation of a floating-point expression during translation yields the same result as the
evaluation of the same expression (or the same operations on the same values) during program
execution.
\begin{example}
\begin{codeblock}
bool f() {
    char array[1 + int(1 + 0.2 - 0.1 - 0.1)];   // Must be evaluated during translation
    int size = 1 + int(1 + 0.2 - 0.1 - 0.1);    // May be evaluated at runtime
    return sizeof(array) == size;
}
\end{codeblock}
It is unspecified whether the value of \tcode{f()} will be \tcode{true} or \tcode{false}.
\end{example}
\end{note}

\rSec2[expr.const.core]{Core constant expressions}

\pnum
\indextext{type!constexpr-unknown representation}%
A type has \defnadj{constexpr-unknown}{representation} if it
\begin{itemize}
\item is a union,
\item is a pointer or pointer-to-member type,
\item is volatile-qualified,
\item is a class type with a non-static data member of reference type, or
\item
has a base class or a non-static member whose
type has constexpr-unknown representation.
\end{itemize}

\pnum
An expression $E$ is a \defnadj{core constant}{expression}
unless the evaluation of $E$, following the rules of the abstract
machine\iref{intro.execution}, would evaluate one of the following:
\begin{itemize}
\item
\keyword{this}\iref{expr.prim.this}, except
\begin{itemize}
\item
in a constexpr function\iref{dcl.constexpr}
that is being evaluated as part of $E$ or
\item
when appearing as the \grammarterm{postfix-expression} of
an implicit or explicit class member access expression\iref{expr.ref};
\end{itemize}

\item
a control flow that passes through
a declaration of a block variable\iref{basic.scope.block} with
static\iref{basic.stc.static} or
thread\iref{basic.stc.thread} storage duration,
unless that variable is usable in constant expressions;
\begin{example}
\begin{codeblock}
constexpr char test() {
  static const int x = 5;
  static constexpr char c[] = "Hello World";
  return *(c + x);
}
static_assert(' ' == test());
\end{codeblock}
\end{example}

\item
an invocation of a non-constexpr function;
\begin{footnote}
Overload resolution\iref{over.match}
is applied as usual.
\end{footnote}

\item
an invocation of an undefined constexpr function;

\item
an invocation of an instantiated constexpr function
that is not constexpr-suitable;

\item
an invocation of a virtual function\iref{class.virtual}
for an object whose dynamic type is constexpr-unknown;

\item
an expression that would exceed the implementation-defined
limits (see \ref{implimits});

\item
an operation that would have undefined or erroneous behavior
as specified in \ref{intro} through \ref{\lastcorechapter};
\begin{footnote}
This includes,
for example, signed integer overflow\iref{expr.pre}, certain
pointer arithmetic\iref{expr.add}, division by
zero\iref{expr.mul}, or certain shift operations\iref{expr.shift}.
\end{footnote}

\item
an lvalue-to-rvalue conversion\iref{conv.lval} unless
it is applied to
\begin{itemize}
  \item
  a glvalue of type \cv{}~\tcode{std::nullptr_t},

  \item
  a non-volatile glvalue that refers to an object that is
  usable in constant expressions, or

  \item
  a non-volatile glvalue of literal type that refers to a non-volatile object
  whose lifetime began within the evaluation of $E$;
\end{itemize}

\item
an lvalue-to-rvalue conversion
that is applied to a glvalue
that refers to a non-active member of a union or a subobject thereof;

\item
an lvalue-to-rvalue conversion that is applied to
an object with an indeterminate value\iref{basic.indet};

\item
an invocation of an implicitly-defined copy/move constructor or
copy/move assignment operator
for a union whose active member (if any) is mutable,
unless the lifetime of the union object began within the evaluation of $E$;

\item
in a \grammarterm{lambda-expression},
a reference to \keyword{this} or to a variable with
automatic storage duration defined outside that
\grammarterm{lambda-expression}, where
the reference would be an odr-use\iref{term.odr.use,expr.prim.lambda};
\begin{example}
\begin{codeblock}
void g() {
  const int n = 0;
  [=] {
    constexpr int i = n;        // OK, \tcode{n} is not odr-used here
    constexpr int j = *&n;      // error: \tcode{\&n} would be an odr-use of \tcode{n}
  };
}
\end{codeblock}
\end{example}
\begin{note}
If the odr-use occurs in an invocation
of a function call operator of a closure type,
it no longer refers to \keyword{this} or to an enclosing
variable with automatic storage duration
due to the transformation\iref{expr.prim.lambda.capture}
of the \grammarterm{id-expression} into
an access of the corresponding data member.
\begin{example}
\begin{codeblock}
auto monad = [](auto v) { return [=] { return v; }; };
auto bind = [](auto m) {
  return [=](auto fvm) { return fvm(m()); };
};

// OK to capture objects with automatic storage duration created during constant expression evaluation.
static_assert(bind(monad(2))(monad)() == monad(2)());
\end{codeblock}
\end{example}
\end{note}

\item
a conversion
from a prvalue \tcode{P} of type ``pointer to \cv{}~\keyword{void}''
to a type ``\cvqual{cv1} pointer to  \tcode{T}'',
where  \tcode{T} is not \cvqual{cv2}~\keyword{void},
unless \tcode{P}
is a null pointer value or
points to an object whose type is similar to \tcode{T};

\item
a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast};

\item
pointer arithmetic\iref{expr.add} where
one (possibly converted) operand
points to the first element of an array of unknown bound and
the other (possibly converted) operand
is of integral type with non-zero value;

\item
a modification of an object\iref{expr.assign,expr.post.incr,expr.pre.incr}
unless it is applied to a non-volatile lvalue of literal type
that refers to a non-volatile object
whose lifetime began within the evaluation of $E$;

\item
an invocation of a destructor\iref{class.dtor} or a function call
whose \grammarterm{postfix-expression} names a pseudo-destructor\iref{expr.call},
in either case for an object whose lifetime did not begin within the evaluation of $E$;

\item
a \grammarterm{new-expression}\iref{expr.new},
unless either
\begin{itemize}
\item
the selected allocation function is
a replaceable global allocation function\iref{new.delete.single,new.delete.array} and
the allocated storage is deallocated within the evaluation of $E$, or
\item
the selected allocation function is
a non-allocating form\iref{new.delete.placement}
with an allocated type \tcode{T}, where
\begin{itemize}
\item
the placement argument to the \grammarterm{new-expression} points
to an object that is transparently replaceable\iref{basic.life} by
the object created by the \grammarterm{new-expression}
or, if \tcode{T} is an array type,
to the first element of such an object, and
\item
the placement argument points to storage
whose duration began within the evaluation of $E$;
\end{itemize}
\end{itemize}

\item
a \grammarterm{delete-expression}\iref{expr.delete},
unless it deallocates a region of storage
allocated within the evaluation of $E$;

\item
a call to an instance of
\tcode{std::allocator<T>::allocate}\iref{allocator.members},
unless the allocated storage is deallocated within the evaluation of $E$;

\item
a call to an instance of
\tcode{std::allocator<T>::deallocate}\iref{allocator.members},
unless it deallocates a region of storage
allocated within the evaluation of $E$;

\item
a construction of an exception object,
unless the exception object and
all of its implicit copies created by invocations of
\tcode{std::current_exception} or \tcode{std::rethrow_exception}\iref{propagation}
are destroyed within the evaluation of $E$;

\item
a \grammarterm{throw-expression}\iref{expr.throw} with no operand,
unless there is a currently handled exception
whose exception object was constructed within the evaluation of $E$;

\item
an \grammarterm{await-expression}\iref{expr.await};

\item
a \grammarterm{yield-expression}\iref{expr.yield};

\item
a three-way comparison\iref{expr.spaceship},
relational\iref{expr.rel}, or equality\iref{expr.eq}
operator where the result is unspecified;

\item
an equality operator comparing pointers to potentially non-unique objects,
if the pointer values of the two operands
are associated with different evaluations\iref{basic.compound} and either
they can both point to the same offset within
the same potentially non-unique object or
one of them points to an object whose
type has constexpr-unknown representation;
\begin{example}
\begin{codeblock}
constexpr const char *f() { return "foo"; }

constexpr bool b1 = +"foo" == "foo";                // error: non-constant
constexpr bool b2 = f() == f();                     // error: non-constant
constexpr const char *p = f();
constexpr bool b3 = p == p;                         // OK, value of \tcode{b3} is \tcode{true}
constexpr bool b4 = "xfoo" + 1 == "foo\0y";         // error: non-constant; string literal
                                                    // object could contain \tcode{"xfoo\textbackslash{}0y"}
constexpr bool b5 = "foo" == "bar" + 0;             // OK, value of \tcode{b5} is \tcode{false}
constexpr bool b6 = (const char*)"foo" == "oo";     // OK, value of \tcode{b6} is \tcode{false}; offsets would
                                                    // be different in a merged string literal object

constexpr std::initializer_list<int *> il1 = { (int *)nullptr };
constexpr std::initializer_list<unsigned long> il2 = { 0 };
constexpr bool b7 = il1.begin() == (void *)il2.begin();     // error: non-constant
\end{codeblock}
\end{example}

\item
a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or
\keyword{typeid}\iref{expr.typeid} expression
on a glvalue that refers to an object
whose dynamic type is constexpr-unknown;

\item
a \tcode{dynamic_cast}\iref{expr.dynamic.cast} expression,
\tcode{typeid}\iref{expr.typeid} expression, or
\tcode{new-expression}\iref{expr.new}
that would throw an exception
where no definition of the exception type is reachable;

\item
an expression that would produce an injected declaration (see below),
unless $E$ is the corresponding expression of
a \grammarterm{consteval-block-declaration}\iref{dcl.pre};

\item
an \grammarterm{asm-declaration}\iref{dcl.asm};

\item
an invocation of the \libmacro{va_arg} macro\iref{cstdarg.syn};

\item
a non-constant library call\iref{defns.nonconst.libcall};
or

\item
a \keyword{goto} statement\iref{stmt.goto}.
\begin{note}
A \keyword{goto} statement introduced by equivalence\iref{stmt}
is not in scope.
For example, a \keyword{while} statement\iref{stmt.while}
can be executed during constant evaluation.
\end{note}
\end{itemize}

\pnum
It is
\impldef{whether an expression is a core constant expression}
whether $E$ is a core constant expression
if $E$ satisfies the constraints of a core constant expression, but
evaluation of $E$ has runtime-undefined behavior.

\pnum
It is unspecified whether $E$ is a core constant expression
if $E$ satisfies the constraints of a core constant expression, but
evaluation of $E$ would evaluate
\begin{itemize}
\item
an operation that has undefined behavior
as specified in \ref{library} through \ref{\lastlibchapter} or
\item
an invocation of the \libmacro{va_start} macro\iref{cstdarg.syn}.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
int x;                              // not constant
struct A {
  constexpr A(bool b) : m(b?42:x) { }
  int m;
};
constexpr int v = A(true).m;        // OK, constructor call initializes \tcode{m} with the value \tcode{42}

constexpr int w = A(false).m;       // error: initializer for \tcode{m} is \tcode{x}, which is non-constant

constexpr int f1(int k) {
  constexpr int x = k;              // error: \tcode{x} is not initialized by a constant expression
                                    // because lifetime of \tcode{k} began outside the initializer of \tcode{x}
  return x;
}
constexpr int f2(int k) {
  int x = k;                        // OK, not required to be a constant expression
                                    // because \tcode{x} is not \keyword{constexpr}
  return x;
}

constexpr int incr(int &n) {
  return ++n;
}
constexpr int g(int k) {
  constexpr int x = incr(k);        // error: \tcode{incr(k)} is not a core constant expression
                                    // because lifetime of \tcode{k} began outside the expression \tcode{incr(k)}
  return x;
}
constexpr int h(int k) {
  int x = incr(k);                  // OK, \tcode{incr(k)} is not required to be a core constant expression
  return x;
}
constexpr int y = h(1);             // OK, initializes \tcode{y} with the value \tcode{2}
                                    // \tcode{h(1)} is a core constant expression because
                                    // the lifetime of \tcode{k} begins inside \tcode{h(1)}
\end{codeblock}
\end{example}

\pnum
For the purposes of determining
whether an expression $E$ is a core constant expression,
the evaluation of the body of a member function of \tcode{std::allocator<T>}
as defined in \ref{allocator.members}, is ignored.

\pnum
For the purposes of determining whether $E$ is a core constant expression,
the evaluation of a call to
a trivial copy/move constructor or copy/move assignment operator of a union
is considered to copy/move the active member of the union, if any.
\begin{note}
The copy/move of the active member is trivial.
\end{note}

\pnum
For the purposes of determining whether $E$ is a core constant expression,
the evaluation of an \grammarterm{id-expression}
that names a structured binding \tcode{v}\iref{dcl.struct.bind} has the
following semantics:
\begin{itemize}
\item
If \tcode{v} is an lvalue referring to the object bound to an invented reference \tcode{r},
the behavior is as if \tcode{r} were nominated.
\item
Otherwise, if \tcode{v} names an array element or class member,
the behavior is that of
evaluating \tcode{$e$[$i$]} or \tcode{$e$.$m$}, respectively,
where $e$ is the name of the variable
initialized from the initializer of the structured binding declaration, and
$i$ is the index of the element referred to by \tcode{v} or
$m$ is the name of the member referred to by \tcode{v}, respectively.
\end{itemize}
\begin{example}
\begin{codeblock}
#include <tuple>
struct S {
  mutable int m;
  constexpr S(int m): m(m) {}
  virtual int g() const;
};
void f(std::tuple<S&> t) {
  auto [r] = t;
  static_assert(r.g() >= 0);            // error: dynamic type is constexpr-unknown
  constexpr auto [m] = S(1);
  static_assert(m == 1);                // error: lvalue-to-rvalue conversion on mutable
                                        // subobject \tcode{e.m}, where \tcode{e} is a constexpr object of type \tcode{S}
  using A = int[2];
  constexpr auto [v0, v1] = A{2, 3};
  static_assert(v0 + v1 == 5);          // OK, equivalent to \tcode{e[0] + e[1]} where \tcode{e} is a constexpr array
}
\end{codeblock}
\end{example}

\pnum
During the evaluation of an expression $E$ as a core constant expression,
all \grammarterm{id-expression}s, \grammarterm{splice-expression}s, and
uses of \tcode{*\keyword{this}}
that refer to an object or reference
whose lifetime did not begin within the evaluation of $E$
are treated as referring to a specific instance of that object or reference
whose lifetime and that of all subobjects (including all union members)
includes the entire constant evaluation.
For such an object that is not usable in constant expressions,
the dynamic type of the object is \defn{constexpr-unknown}.
For such a reference that is not usable in constant expressions,
the reference is treated as binding to
an unspecified object of the referenced type
whose lifetime and that of all subobjects includes
the entire constant evaluation and whose dynamic type is constexpr-unknown.
\begin{example}
\begin{codeblock}
template <typename T, size_t N>
constexpr size_t array_size(T (&)[N]) {
  return N;
}

void use_array(int const (&gold_medal_mel)[2]) {
  constexpr auto gold = array_size(gold_medal_mel);     // OK
}

constexpr auto olympic_mile() {
  const int ledecky = 1500;
  return []{ return ledecky; };
}
static_assert(olympic_mile()() == 1500);                // OK

struct Swim {
  constexpr int phelps() { return 28; }
  virtual constexpr int lochte() { return 12; }
  int coughlin = 12;
};

constexpr int how_many(Swim& swam) {
  Swim* p = &swam;
  return (p + 1 - 1)->phelps();
}

void splash(Swim& swam) {
  static_assert(swam.phelps() == 28);           // OK
  static_assert((&swam)->phelps() == 28);       // OK

  Swim* pswam = &swam;
  static_assert(pswam->phelps() == 28);         // error: lvalue-to-rvalue conversion on a pointer
                                                // not usable in constant expressions

  static_assert(how_many(swam) == 28);          // OK
  static_assert(Swim().lochte() == 12);         // OK

  static_assert(swam.lochte() == 12);           // error: invoking virtual function on reference
                                                // with constexpr-unknown dynamic type

  static_assert(swam.coughlin == 12);           // error: lvalue-to-rvalue conversion on an object
                                                // not usable in constant expressions
}

extern Swim dc;
extern Swim& trident;

constexpr auto& sandeno   = typeid(dc);         // OK, can only be \tcode{typeid(Swim)}
constexpr auto& gallagher = typeid(trident);    // error: constexpr-unknown dynamic type
\end{codeblock}
\end{example}

\rSec2[expr.const.const]{Constant expressions}

\pnum
A \defnadj{constant}{expression} is either
\begin{itemize}
\item
a glvalue core constant expression $E$ for which
\begin{itemize}
\item
$E$ refers to a non-immediate function,
\item
$E$ designates an object \tcode{o}, and
if the complete object of \tcode{o} is of consteval-only type then so is $E$,
\begin{example}
\begin{codeblock}
struct Base { };
struct Derived : Base { std::meta::info r; };

consteval const Base& fn(const Derived& derived) { return derived; }

constexpr Derived obj{.r=^^::};     // OK
constexpr const Derived& d = obj;   // OK
constexpr const Base& b = fn(obj);  // error: not a constant expression because \tcode{Derived}
                                    // is a consteval-only type but \tcode{Base} is not.
\end{codeblock}
\end{example}
\end{itemize}
or
\item
a prvalue core constant expression whose result object\iref{basic.lval} (if any)
satisfies the following constraints:
\begin{itemize}
\item
each constituent reference refers to an object or a non-immediate function,
\item
no constituent value of scalar type is an indeterminate or erroneous value\iref{basic.indet},
\item
no constituent value of pointer type is a pointer to an immediate function or
an invalid pointer value\iref{basic.compound},
\item
no constituent value of pointer-to-member type designates an immediate function, and
\item
unless the value is of consteval-only type,
\begin{itemize}
\item
no constituent value of pointer-to-member type points to
a direct member of a consteval-only class type,
\item
no constituent value of pointer type points to or past an object
whose complete object is of consteval-only type, and
\item
no constituent reference refers to an object
whose complete object is of consteval-only type.
\end{itemize}
\end{itemize}
\end{itemize}
\begin{note}
A glvalue core constant expression
that either refers to or points to an unspecified object
is not a constant expression.
\end{note}
\begin{example}
\begin{codeblock}
consteval int f() { return 42; }
consteval auto g() { return f; }
consteval int h(int (*p)() = g()) { return p(); }
constexpr int r = h();                          // OK
constexpr auto e = g();                         // error: a pointer to an immediate function is
                                                // not a permitted result of a constant expression

struct S {
  int x;
  constexpr S() {}
};
int i() {
  constexpr S s;                                // error: \tcode{s.x} has erroneous value
}
\end{codeblock}
\end{example}

\pnum
An \defnadj{integral constant}{expression}
is an expression of integral or
unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression.
\begin{note}
Such expressions can be
used as bit-field lengths\iref{class.bit}, as enumerator
initializers if the underlying type is not fixed\iref{dcl.enum},
and as alignments\iref{dcl.align}.
\end{note}

\pnum
If an expression of literal class type is used in a context where an
integral constant expression is required, then that expression is
contextually implicitly converted\iref{conv} to an integral or unscoped
enumeration type
and the selected conversion function shall be \keyword{constexpr}.
\begin{example}
\begin{codeblock}
struct A {
  constexpr A(int i) : val(i) { }
  constexpr operator int() const { return val; }
  constexpr operator long() const { return 42; }
private:
  int val;
};
constexpr A a = alignof(int);
alignas(a) int n;               // error: ambiguous conversion
struct B { int n : a; };        // error: ambiguous conversion
\end{codeblock}
\end{example}

\pnum
A \defnadj{converted constant}{expression}
of type \tcode{T} is an
expression, implicitly converted to type \tcode{T}, where
the converted expression is a constant expression and the
implicit conversion sequence contains only
\begin{itemize}
\item user-defined conversions,
\item lvalue-to-rvalue conversions\iref{conv.lval},
\item array-to-pointer conversions\iref{conv.array},
\item function-to-pointer conversions\iref{conv.func},
\item qualification conversions\iref{conv.qual},
\item integral promotions\iref{conv.prom},
\item integral conversions\iref{conv.integral} other than narrowing conversions\iref{dcl.init.list},
\item floating-point promotions\iref{conv.fpprom},
\item floating-point conversions\iref{conv.double} where
  the source value can be represented exactly in the destination type,
\item null pointer conversions\iref{conv.ptr} from \tcode{std::nullptr_t},
\item null member pointer conversions\iref{conv.mem} from \tcode{std::nullptr_t}, and
\item function pointer conversions\iref{conv.fctptr},
\end{itemize}
and where the reference binding (if any) binds directly.
\begin{note}
Such expressions can be used in \keyword{new}
expressions\iref{expr.new}, as case expressions\iref{stmt.switch},
as enumerator initializers if the underlying type is
fixed\iref{dcl.enum}, as array bounds\iref{dcl.array},
as constant template arguments\iref{temp.arg},
and as the constant expression of a \grammarterm{splice-specifier}\iref{basic.splice}.
\end{note}
\indextext{contextually converted constant expression of type \tcode{bool}|see{conversion, contextual}}%
\indextext{conversion!contextual to constant expression of type \tcode{bool}}%

\pnum
A \term{contextually converted constant expression of type \tcode{bool}} is
an expression, contextually converted to \keyword{bool}\iref{conv},
where the converted expression is a constant expression and
the conversion sequence contains only the conversions above.

\rSec2[expr.const.init]{Constant initialization}

\pnum
The constituent values and constituent references of
a variable \tcode{x} are defined as follows:
\begin{itemize}
\item
If \tcode{x} declares an object,
the constituent values and references of that object\iref{intro.object} are
constituent values and references of \tcode{x}.
\item
If \tcode{x} declares a reference,
that reference is a constituent reference of \tcode{x}.
\end{itemize}
For any constituent reference \tcode{r} of a variable \tcode{x},
if \tcode{r} is bound to a temporary object or subobject thereof
whose lifetime is extended to that of \tcode{r},
the constituent values and references of that temporary object
are also constituent values and references of \tcode{x}, recursively.

\pnum
An object $o$ is \defn{constexpr-referenceable} from a point $P$ if
\begin{itemize}
\item
$o$ has static storage duration, or
\item
$o$ has automatic storage duration, and, letting \tcode{v} denote
\begin{itemize}
\item
the variable corresponding to $o$'s complete object or
\item
the variable to whose lifetime that of $o$ is extended,
\end{itemize}
the smallest scope enclosing \tcode{v} and the smallest scope enclosing $P$
that are neither
\begin{itemize}
\item
block scopes nor
\item
function parameter scopes associated with
a \grammarterm{requirement-parameter-list}
\end{itemize}
are the same function parameter scope.
\end{itemize}
\begin{example}
\begin{codeblock}
struct A {
  int m;
  const int& r;
};
void f() {
  static int sx;
  thread_local int tx;                  // \tcode{tx} is never constexpr-referenceable
  int ax;
  A aa = {1, 2};
  static A sa = {3, 4};
  // The objects \tcode{sx}, \tcode{ax}, and \tcode{aa.m}, \tcode{sa.m}, and the temporaries to which \tcode{aa.r} and \tcode{sa.r} are bound, are constexpr-referenceable.
  auto lambda = [] {
    int ay;
    // The objects \tcode{sx}, \tcode{sa.m}, and \tcode{ay} (but not \tcode{ax} or \tcode{aa}), and the
    // temporary to which \tcode{sa.r} is bound, are constexpr-referenceable.
  };
}
\end{codeblock}
\end{example}

\pnum
An object or reference \tcode{x} is
\defn{constexpr-representable} at a point $P$ if,
for each constituent value of \tcode{x} that points to or past an object $o$,
and for each constituent reference of \tcode{x} that refers to an object $o$,
$o$ is constexpr-referenceable from $P$.

\pnum
\indextext{contract evaluation semantics!ignore}
A variable \tcode{v} is \defn{constant-initializable} if
\begin{itemize}
\item
the full-expression of its initialization is a constant expression
when interpreted as a \grammarterm{constant-expression}
with all contract assertions
using the ignore evaluation semantic\iref{basic.contract.eval},
\begin{note}
In the course of this determination,
\tcode{std::is_constant_evaluated()}\iref{meta.const.eval}
has the value \keyword{true}.
\end{note}
\begin{note}
Furthermore, if the initialization is manifestly constant-evaluated\iref{expr.const.defns},
its evaluation during translation
can still evaluate contract assertions
with other evaluation semantics,
resulting in a diagnostic or ill-formed program
if a contract violation occurs.
\end{note}
\item
immediately after the initializing declaration of \tcode{v},
the object or reference \tcode{x} declared by \tcode{v}
is constexpr-representable, and
\item
if \tcode{x} has static or thread storage duration,
\tcode{x} is constexpr-representable at the nearest point
whose immediate scope is a namespace scope
that follows the initializing declaration of \tcode{v}.
\end{itemize}

\pnum
A constant-initializable variable is \defn{constant-initialized}
if either it has an initializer or
its type is const-default-constructible\iref{dcl.init.general}.
\begin{example}
\begin{codeblock}
void f() {
  int ax = 0;                   // \tcode{ax} is constant-initialized
  thread_local int tx = 0;      // \tcode{tx} is constant-initialized
  static int sx;                // \tcode{sx} is not constant-initialized
  static int& rss = sx;         // \tcode{rss} is constant-initialized
  static int& rst = tx;         // \tcode{rst} is not constant-initialized
  static int& rsa = ax;         // \tcode{rsa} is not constant-initialized
  thread_local int& rts = sx;   // \tcode{rts} is constant-initialized
  thread_local int& rtt = tx;   // \tcode{rtt} is not constant-initialized
  thread_local int& rta = ax;   // \tcode{rta} is not constant-initialized
  int& ras = sx;                // \tcode{ras} is constant-initialized
  int& rat = tx;                // \tcode{rat} is not constant-initialized
  int& raa = ax;                // \tcode{raa} is constant-initialized
}
\end{codeblock}
\end{example}

\pnum
A variable is \defn{potentially-constant} if
it is constexpr or
it has reference or non-volatile const-qualified integral or enumeration type.

\pnum
A variable $V$ is
\defnx{usable in constant expressions}{usable in constant expressions!variable} at a point $P$ if
$V$ is constant-initialized and potentially-constant,
$V$'s initializing declaration $D$ is reachable from $P$, and
\begin{itemize}
\item $V$ is constexpr,
\item $V$ is not initialized to a TU-local value, or
\item $P$ is in the same translation unit as $D$.
\end{itemize}

\pnum
An object or reference is
\defn{potentially usable in constant expressions} at point $P$ if it is
\begin{itemize}
\item
the object or reference declared by a variable
that is usable in constant expressions at $P$,
\item
a temporary object of non-volatile const-qualified literal type
whose lifetime is extended\iref{class.temporary}
to that of a variable that is usable in constant expressions at $P$,
\item
a template parameter object\iref{temp.param},
\item
a string literal object\iref{lex.string},
\item
a non-mutable subobject of any of the above, or
\item
a reference member of any of the above.
\end{itemize}

\pnum
An object or reference is
\defnx{usable in constant expressions}{usable in constant expressions!object or reference}
at point $P$
if it is an object or reference
that is potentially usable in constant expressions at $P$ and
is constexpr-representable at $P$.
\begin{example}
\begin{codeblock}
struct A {
  int* const & r;
};
void f(int x) {
  constexpr A a = {&x};
  static_assert(a.r == &x);             // OK
  [&] {
    static_assert(a.r != nullptr);      // error: \tcode{a.r} is not usable in constant expressions at this point
  }();
}
\end{codeblock}
\end{example}

\rSec2[expr.const.imm]{Immediate functions}

\pnum
An expression or conversion is in an \defn{immediate function context}
if it is potentially evaluated and either:
\begin{itemize}
\item
its innermost enclosing non-block scope is
a function parameter scope of an immediate function,
\item
it is a subexpression of a manifestly constant-evaluated expression
or conversion\iref{expr.const.defns}, or
\item
its enclosing statement is enclosed\iref{stmt.pre} by
the \grammarterm{compound-statement} of a consteval if statement\iref{stmt.if}.
\end{itemize}
An invocation is an \defn{immediate invocation}
if it is a potentially evaluated explicit or implicit invocation of
an immediate function and
is not in an immediate function context.
An aggregate initialization is an immediate invocation
if it evaluates a default member initializer
that has a subexpression that is an immediate-escalating expression.

\pnum
\indexdefn{expression!immediate-escalating}%
\indexdefn{conversion!immediate-escalating}%
\indexdefn{immediate-escalating!expression|see{expression, immediate-escalating}}%
\indexdefn{immediate-escalating!conversion|see{conversion, immediate-escalating}}%
A potentially evaluated expression or conversion is \defn{immediate-escalating}
if it is neither initially in an immediate function context
nor a subexpression of an immediate invocation, and
\begin{itemize}
\item
it is an \grammarterm{id-expression} or \grammarterm{splice-expression}
that designates an immediate function,
\item
it is an immediate invocation that is not a constant expression, or
\item
it is of consteval-only type\iref{basic.types.general}.
\end{itemize}

\pnum
\indexdefn{immediate-escalating!function|see{function, immediate-escalating}}%
An \defnx{immediate-escalating}{function!immediate-escalating} function is
\begin{itemize}
\item
the call operator of a lambda that is not declared
with the \keyword{consteval} specifier,
\item
a non-user-provided defaulted function
that is not declared with the \keyword{consteval} specifier, or
\item
a function that is not a prospective destructor and
that results from the instantiation
of a templated entity defined with the \keyword{constexpr} specifier.
\end{itemize}
An immediate-escalating expression shall appear only
in an immediate-escalating function.

\pnum
An \defnadj{immediate}{function} is a function that is
\begin{itemize}
\item
declared with the \keyword{consteval} specifier,
\item
an immediate-escalating function
whose type is consteval-only\iref{basic.types.general}, or
\item
an immediate-escalating function \tcode{\placeholder{F}}
whose function body contains either
\begin{itemize}
\item an immediate-escalating expression or
\item a definition of a non-constexpr variable with consteval-only type
\end{itemize}
whose innermost enclosing non-block scope
is \tcode{\placeholder{F}}'s function parameter scope.
\begin{tailnote}
Default member initializers used to initialize
a base or member subobject\iref{class.base.init}
are considered to be part of the function body\iref{dcl.fct.def.general}.
\end{tailnote}
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
consteval int id(int i) { return i; }
constexpr char id(char c) { return c; }

template<class T>
constexpr int f(T t) {
  return t + id(t);
}

auto a = &f<char>;              // OK, \tcode{f<char>} is not an immediate function
auto b = &f<int>;               // error: \tcode{f<int>} is an immediate function

static_assert(f(3) == 6);       // OK

template<class T>
constexpr int g(T t) {          // \tcode{g<int>} is not an immediate function
  return t + id(42);            // because \tcode{id(42)} is already a constant
}

template<class T, class F>
constexpr bool is_not(T t, F f) {
  return not f(t);
}

consteval bool is_even(int i) { return i % 2 == 0; }

static_assert(is_not(5, is_even));      // OK

int x = 0;

template<class T>
constexpr T h(T t = id(x)) {    // \tcode{h<int>} is not an immediate function
                                // \tcode{id(x)} is not evaluated when parsing the default argument\iref{dcl.fct.default,temp.inst}
    return t;
}

template<class T>
constexpr T hh() {              // \tcode{hh<int>} is an immediate function because of the invocation
  return h<T>();                // of the immediate function \tcode{id} in the default argument of \tcode{h<int>}
}

int i = hh<int>();              // error: \tcode{hh<int>()} is an immediate-escalating expression
                                // outside of an immediate-escalating function

struct A {
  int x;
  int y = id(x);
};

template<class T>
constexpr int k(int) {          // \tcode{k<int>} is not an immediate function because \tcode{A(42)} is a
  return A(42).y;               // constant expression and thus not immediate-escalating
}

constexpr int l(int c) pre(c >= 2) {
  return (c % 2 == 0) ? c / 0 : c;
}

const int i0 = l(0);    // dynamic initialization; contract violation or undefined behavior
const int i1 = l(1);    // static initialization; value of \tcode{1} or contract violation at compile time
const int i2 = l(2);    // dynamic initialization; undefined behavior
const int i3 = l(3);    // static initialization; value of \tcode{3}
\end{codeblock}
\end{example}

\rSec2[expr.const.reflect]{Reflection}

\pnum
The evaluation of an expression can introduce
one or more \defnadjx{injected}{declarations}{declaration}.
The evaluation is said to \defn{produce} the declarations.
\begin{note}
An invocation of
the library function template \tcode{std::meta::define_aggregate}
produces an injected declaration\iref{meta.reflection.define.aggregate}.
\end{note}
Each such declaration has
\begin{itemize}
\item
an associated \defnadj{synthesized}{point},
which follows the last non-synthesized program point
in the translation unit containing that declaration, and
\item
an associated \defnadj{characteristic}{sequence} of values.
\end{itemize}
\begin{note}
Special rules concerning reachability
apply to synthesized points\iref{module.reach}.
\end{note}
\begin{note}
The program is ill-formed
if injected declarations with different characteristic sequences
define the same entity in different translation units\iref{basic.def.odr}.
\end{note}

\pnum
A member of an entity defined by an injected declaration
shall not have a name reserved to the implementation\iref{lex.name};
no diagnostic is required.

\pnum
Let $C$ be a \grammarterm{consteval-block-declaration},
the evaluation of whose corresponding expression
produces an injected declaration for an entity $E$.
The program is ill-formed if either
\begin{itemize}
\item
$C$ is enclosed by a scope associated with $E$ or
\item
letting $P$ be a point whose immediate scope is that to which $E$ belongs,
there is a function parameter scope or class scope
that encloses exactly one of $C$ or $P$.
\end{itemize}

\pnum
\begin{example}
\begin{codeblock}
struct S0 {
  consteval {
    std::meta::define_aggregate(^^S0, {});  // error: scope associated with \tcode{S0} encloses the consteval block
  }
};

struct S1;
consteval { std::meta::define_aggregate(^^S1, {}); }    // OK

template <std::meta::info R> consteval void tfn1() {
  std::meta::define_aggregate(R, {});
}

struct S2;
consteval { tfn1<^^S2>(); }                             // OK

template <std::meta::info R> consteval void tfn2() {
  consteval { std::meta::define_aggregate(R, {}); }
}

struct S3;
consteval { tfn2<^^S3>(); }
  // error: function parameter scope of \tcode{tfn2<\caret\caret S3>} intervenes between the declaration of \tcode{S3}
  // and the consteval block that produces the injected declaration

template <typename> struct TCls {
  struct S4;
  static void sfn() requires ([] {
    consteval { std::meta::define_aggregate(^^S4, {}); }
    return true;
  }()) { }
};

consteval { TCls<void>::sfn(); }    // error: \tcode{TCls<void>::S4} is not enclosed by \grammarterm{requires-clause} lambda

struct S5;
struct Cls {
  consteval { std::meta::define_aggregate(^^S5, {}); }  // error: \tcode{S5} is not enclosed by class \tcode{Cls}
};

struct S6;
consteval {                                 // \#1
  struct S7;                                // local class

  std::meta::define_aggregate(^^S7, {});    // error: consteval block \#1 does not enclose itself,
                                            // but encloses \tcode{S7}

  struct S8;                                // local class
  consteval {                               // \#2
    std::meta::define_aggregate(^^S6, {});  // error: consteval block \#1 encloses
                                            // consteval block \#2 but not \tcode{S6}

    std::meta::define_aggregate(^^S8, {});  // OK, consteval block \#1 encloses both \#2 and \tcode{S8}
  }
}
\end{codeblock}
\end{example}

\pnum
During an evaluation $V$\iref{intro.execution} of
an expression, conversion, or initialization $E$
as a core constant expression, the
\indextext{point of!evaluation}%
\indextext{point!of evaluation}%
\indextext{evaluation!point of evaluation, during}%
\defnx{point of evaluation of $E$ during $V$}{point of evaluation during evaluation}
is the program point $P$ determined as follows:
\begin{itemize}
\item
If $E$ is a potentially-evaluated subexpression of
a default member initializer $I$, and
$V$ is the evaluation of $E$ in the evaluation of $I$
as an immediate subexpression of a (possibly aggregate) initialization, then
$P$ is the point of evaluation of that initialization.
\begin{tailnote}
For example,
$E$ can be an immediate invocation in a default member initializer
used by an aggregate initialization appearing at $P$.
\end{tailnote}

\item
Otherwise,
if $E$ is a potentially-evaluated subexpression of
a default argument $A$\iref{dcl.fct.default}, and
$V$ is the evaluation of $E$ in the evaluation of $A$ as
an immediate subexpression of a function call\iref{expr.call}, then
$P$ is the point of evaluation of that function call.

\item
Otherwise,
$P$ is the point at which $E$ appears.
\end{itemize}
During the evaluation $V$ of an expression $E$ as a core constant expression,
the \defnadj{evaluation}{context} of an evaluation $X$
during $V$ is the set $C$ of program points determined as follows:
\begin{itemize}
\item
If $X$ occurs during the evaluation $Y$ of
a manifestly constant-evaluated expression,
where $Y$ occurs during $V$, then
$C$ is the evaluation context of $X$ during $Y$.
\item
Otherwise, $C$ contains
  \begin{itemize}
  \item
  the point of evaluation of $E$ during $V$ and
  each synthesized point in the instantiation context thereof and
  \item
  each synthesized point corresponding to an injected declaration
  produced by any evaluation executed during $V$ that
  is sequenced before $X$\iref{intro.execution}.
  \end{itemize}
\end{itemize}
\begin{note}
The evaluation context determines the behavior of certain functions
used for reflection\iref{meta.reflection}.
\end{note}
\begin{example}
\begin{codeblock}
struct S;
consteval std::size_t f(int p) {
  constexpr std::size_t r = /* @\tcode{Q}@ */
    std::meta::is_complete_type(^^S) ? 1 : 2;   // \#1
  if (!std::meta::is_complete_type(^^S)) {      // \#2
    std::meta::define_aggregate(^^S, {});
  }
  return (p > 0) ? f(p - 1) : r;
}

consteval {
  if (f(1) != 2) {
    throw;                                      // OK, not evaluated
  }
}
\end{codeblock}
During each evaluation of
\tcode{std::meta::is_complete_type(\caret\caret{}S)}
at \#1\iref{meta.reflection.queries} that is
executed during the evaluation of \tcode{f(1) != 2},
the evaluation context contains \tcode{Q},
but does not contain the synthesized point
associated with the injected declaration of \tcode{S}.
However, the synthesized point is in the evaluation context of
\tcode{std::meta::is_complete_type(\caret\caret{}S)} at \#2
during the evaluation of \tcode{f(0)}.
\end{example}

\rSec2[expr.const.defns]{Further definitions}

\pnum
An expression or conversion is \defn{manifestly constant-evaluated}
if it is
\begin{itemize}
\item a \grammarterm{constant-expression}, or
\item the condition of a constexpr if statement\iref{stmt.if}, or
\item the expression corresponding to
a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, or
\item an immediate invocation, or
\item the result of substitution into an atomic constraint expression
to determine whether it is satisfied\iref{temp.constr.atomic}, or
\item the initializer of a variable
that is usable in constant expressions or
has constant initialization\iref{basic.start.static}.
\begin{footnote}
Testing this condition
can involve a notional evaluation of its initializer,
with evaluations of contract assertions
using the ignore evaluation semantic\iref{basic.contract.eval},
as described above.
\end{footnote}
\begin{example}
\begin{codeblock}
template<bool> struct X {};
X<std::is_constant_evaluated()> x;                      // type \tcode{X<true>}
int y;
const int a = std::is_constant_evaluated() ? y : 1;     // dynamic initialization to 1
double z[a];                                            // error: \tcode{a} is not usable
                                                        // in constant expressions
const int b = std::is_constant_evaluated() ? 2 : y;     // static initialization to 2
int c = y + (std::is_constant_evaluated() ? 2 : y);     // dynamic initialization to \tcode{y+y}

constexpr int f() {
  const int n = std::is_constant_evaluated() ? 13 : 17; // \tcode{n} is 13
  int m = std::is_constant_evaluated() ? 13 : 17;       // \tcode{m} can be 13 or 17 (see below)
  char arr[n] = {};                                     // \tcode{char[13]}
  return m + sizeof(arr);
}
int p = f();                                            // \tcode{m} is 13; initialized to 26
int q = p + f();                                        // \tcode{m} is 17 for this call; initialized to 56
\end{codeblock}
\end{example}
\end{itemize}
\begin{note}
Except for a \grammarterm{static_assert-message},
a manifestly constant-evaluated expression
is evaluated even in an unevaluated operand\iref{term.unevaluated.operand}.
\end{note}

\pnum
\indextext{expression!potentially constant evaluated}%
An expression or conversion is \defn{potentially constant evaluated}
if it is:
\begin{itemize}
\item
a manifestly constant-evaluated expression,

\item
a potentially evaluated expression\iref{basic.def.odr},

\item
an immediate subexpression of a \grammarterm{braced-init-list},
\begin{footnote}
In some cases, constant evaluation is needed to determine whether a narrowing conversion is performed\iref{dcl.init.list}.
\end{footnote}

\item
an expression of the form \tcode{\&} \grammarterm{cast-expression}
that occurs within a templated entity,
\begin{footnote}
In some cases, constant evaluation is needed to determine whether such an expression is value-dependent\iref{temp.dep.constexpr}.
\end{footnote}
or

\item
a potentially-evaluated subexpression\iref{intro.execution} of one of the above.
\end{itemize}

\indextext{function!needed for constant evaluation}%
\indextext{variable!needed for constant evaluation}%
A function or variable is
\defn{needed for constant evaluation}
if it is:
\begin{itemize}
\item
a constexpr function that is named by an expression\iref{basic.def.odr}
that is potentially constant evaluated, or

\item
a potentially-constant variable named by a potentially constant evaluated expression.
\end{itemize}

\pnum
An object \tcode{a} is said to have \defnadj{constant}{destruction} if
\begin{itemize}
\item
  it is not of class type nor (possibly multidimensional) array thereof, or
\item
  it is of class type or (possibly multidimensional) array thereof,
  that class type has a constexpr destructor\iref{dcl.constexpr}, and
  for a hypothetical expression $E$
  whose only effect is to destroy \tcode{a},
  $E$ would be a core constant expression
  if the lifetime of \tcode{a} and its non-mutable subobjects
  (but not its mutable subobjects) were considered to start within $E$.
\end{itemize}

\indextext{expression|)}
