Files
cppdraft_translate/cppdraft/expr/compound.md
2025-10-25 03:02:53 +03:00

5037 lines
255 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[expr.compound]
# 7 Expressions [[expr]](./#expr)
## 7.6 Compound expressions [expr.compound]
### [7.6.1](#expr.post) Postfix expressions [[expr.post]](expr.post)
#### [7.6.1.1](#expr.post.general) General [[expr.post.general]](expr.post.general)
[1](#expr.post.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3658)
Postfix expressions group left-to-right[.](#expr.post.general-1.sentence-1)
[postfix-expression:](#nt:postfix-expression "7.6.1.1General[expr.post.general]")
[*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1Grammar[expr.prim.grammar]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") [ [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]")opt ]
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") ( [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ( [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") ( [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") . templateopt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") . [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") -> templateopt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") -> [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") ++
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") --
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
[expression-list:](#nt:expression-list "7.6.1.1General[expr.post.general]")
[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]")
[2](#expr.post.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3689)
[*Note [1](#expr.post.general-note-1)*:
The > token following the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") in a dynamic_cast,static_cast, reinterpret_cast, orconst_cast can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3Names of template specializations"))[.](#expr.post.general-2.sentence-1)
— *end note*]
#### [7.6.1.2](#expr.sub) Subscripting [[expr.sub]](expr.sub)
[1](#expr.sub-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3701)
A [*subscript expression*](#def:expression,subscript "7.6.1.2Subscripting[expr.sub]") is a postfix expression
followed by square brackets containing
a possibly empty, comma-separated list of [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* that constitute the arguments to the subscript operator[.](#expr.sub-1.sentence-1)
The [*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") and
the initialization of the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of
any applicable subscript operator function ([[over.sub]](over.sub "12.4.5Subscripting")) is sequenced before
each expression in the [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") and also before
any default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#expr.sub-1.sentence-2)
The initialization of a non-object parameter of
a subscript operator function S,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of
any other non-object parameter of S[.](#expr.sub-1.sentence-3)
[2](#expr.sub-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3719)
With the built-in subscript operator,
an [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") shall be present,
consisting of a single [*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#expr.sub-2.sentence-1)
One of the expressions shall be a glvalue of type “array ofT” or a prvalue of type “pointer
to T” and the other shall be a prvalue of unscoped enumeration or integral type[.](#expr.sub-2.sentence-2)
The result is of type “€[.](#expr.sub-2.sentence-3)
The type “€ shall be a completely-defined object type[.](#expr.sub-2.sentence-4)[48](#footnote-48 "This is true even if the subscript operator is used in the following common idiom: &amp;x[0].")
The expression E1[E2] is identical (by definition) to*((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[.](#expr.sub-2.sentence-5)
[3](#expr.sub-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3739)
[*Note [1](#expr.sub-note-1)*:
Despite its asymmetric appearance, subscripting is a commutative
operation except for sequencing[.](#expr.sub-3.sentence-1)
See [[expr.unary]](#expr.unary "7.6.2Unary expressions") and [[expr.add]](#expr.add "7.6.6Additive operators") for details of * and+ and [[dcl.array]](dcl.array "9.3.4.5Arrays") for details of array types[.](#expr.sub-3.sentence-2)
— *end note*]
[48)](#footnote-48)[48)](#footnoteref-48)
This
is true even if the subscript operator is used in the following common idiom:&x[0][.](#footnote-48.sentence-1)
#### [7.6.1.3](#expr.call) Function call [[expr.call]](expr.call)
[1](#expr.call-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3749)
A function call is a postfix expression followed by parentheses
containing a possibly empty, comma-separated list of[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* which
constitute the arguments to the function[.](#expr.call-1.sentence-1)
[*Note [1](#expr.call-note-1)*:
If the postfix expression is a function or member function name,
the appropriate function and the validity of the call
are determined according to the rules in [[over.match]](over.match "12.2Overload resolution")[.](#expr.call-1.sentence-2)
— *end note*]
The postfix expression shall
have function type or function pointer type[.](#expr.call-1.sentence-3)
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 ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion")) is suppressed on the postfix expression),
or a prvalue of function pointer type[.](#expr.call-1.sentence-4)
[2](#expr.call-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3770)
If the selected
function is non-virtual, or if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") in the class
member access expression is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]"), that function is
called[.](#expr.call-2.sentence-1)
Otherwise, its [final overrider](class.virtual#def:final_overrider "11.7.3Virtual functions[class.virtual]") in the dynamic type
of the object expression is called; such a call is referred to as a[*virtual function call*](#def:function,virtual_function_call "7.6.1.3Function call[expr.call]")[.](#expr.call-2.sentence-2)
[*Note [2](#expr.call-note-2)*:
The dynamic type is the type of the object referred to by the
current value of the object expression[.](#expr.call-2.sentence-3)
[[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describes the
behavior of virtual function calls when the object expression
refers to
an object under construction or destruction[.](#expr.call-2.sentence-4)
— *end note*]
[3](#expr.call-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3785)
[*Note [3](#expr.call-note-3)*:
If a function or member function name is used, and [name
lookup](basic.lookup "6.5Name lookup[basic.lookup]") does not find a declaration of that name,
the program is ill-formed[.](#expr.call-3.sentence-1)
No function is implicitly declared by such a
call[.](#expr.call-3.sentence-2)
— *end note*]
[4](#expr.call-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3793)
If the [*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") names
a destructor or pseudo-destructor ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5Destruction")),
the type of the function call expression is void; otherwise, the
type of the function call expression is the return type of the
statically chosen function (i.e., ignoring the virtual keyword),
even if the type of the function actually called is different[.](#expr.call-4.sentence-1)
If the [*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") names a pseudo-destructor
(in which case the [*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") 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 ([[expr.ref]](#expr.ref "7.6.1.5Class member access"), [[basic.life]](basic.life "6.8.4Lifetime"))[.](#expr.call-4.sentence-2)
[5](#expr.call-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3809)
A type Tcall is[*call-compatible*](#def:call-compatible "7.6.1.3Function call[expr.call]") with a function type Tfunc if Tcall is the same type as Tfunc or
if the type “pointer to Tfunc” can be
converted to type “pointer to Tcall”
via a function pointer conversion ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions"))[.](#expr.call-5.sentence-1)
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[.](#expr.call-5.sentence-2)
[*Note [4](#expr.call-note-4)*:
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[.](#expr.call-5.sentence-3)
— *end note*]
[6](#expr.call-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3829)
When a function is called, each parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) is
initialized ([[dcl.init]](dcl.init "9.5Initializers"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")) with
its corresponding argument,
and each precondition assertion of the function
is evaluated ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#expr.call-6.sentence-1)
If the function is an explicit object member function and
there is an implied object argument ([[over.call.func]](over.call.func "12.2.2.2.2Call to designated function")),
the list of provided arguments is preceded by the implied object argument
for the purposes of this correspondence[.](#expr.call-6.sentence-2)
If there is no corresponding argument,
the default argument for the parameter is used[.](#expr.call-6.sentence-3)
[*Example [1](#expr.call-example-1)*: template<typename ...T> int f(int n = 0, T ...t);int x = f<int>(); // error: no argument for second function parameter — *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 ([[over.match.funcs]](over.match.funcs "12.2.2Candidate functions and argument lists"))
is initialized with that glvalue,
converted as if by an [explicit type conversion](#expr.cast "7.6.3Explicit type conversion (cast notation)[expr.cast]")[.](#expr.call-6.sentence-4)
[*Note [5](#expr.call-note-5)*:
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[.](#expr.call-6.sentence-5)
See [[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"), [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"),
and [[expr.ref]](#expr.ref "7.6.1.5Class member access")[.](#expr.call-6.sentence-6)
— *end note*]
When a function is called, the type of any parameter
shall not be a class type that is either incomplete or abstract[.](#expr.call-6.sentence-7)
[*Note [6](#expr.call-note-6)*:
This still allows a parameter to be a pointer or reference to such
a type[.](#expr.call-6.sentence-8)
However, it prevents a passed-by-value parameter
to have an incomplete or abstract class type[.](#expr.call-6.sentence-9)
— *end note*]
It is implementation-defined
whether a parameter is destroyed
when the function in which it is defined exits ([[stmt.return]](stmt.return "8.8.4The return statement"), [[except.ctor]](except.ctor "14.3Stack unwinding"), [[expr.await]](#expr.await "7.6.2.4Await"))
or at the end of the enclosing full-expression;
parameters are always destroyed in the reverse order of their construction[.](#expr.call-6.sentence-10)
The initialization and destruction of each parameter occurs
within the context of the full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))
where the function call appears[.](#expr.call-6.sentence-11)
[*Example [2](#expr.call-example-2)*:
The access ([[class.access.general]](class.access.general "11.8.1General")) of the
constructor, conversion functions, or destructor is
checked at the point of call[.](#expr.call-6.sentence-12)
If a constructor
or destructor for a function parameter throws an exception,
any [*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") ([[except.pre]](except.pre "14.1Preamble"))
of the called function
with a handler that can handle the exception
is not considered[.](#expr.call-6.sentence-13)
— *end example*]
[7](#expr.call-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3890)
The [*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]") is sequenced before
each [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") in the [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") and any default argument[.](#expr.call-7.sentence-1)
The initialization of a parameter or,
if the implementation introduces any temporary objects
to hold the values of function parameters ([[class.temporary]](class.temporary "6.8.7Temporary objects")),
the initialization of those temporaries,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of any other parameter[.](#expr.call-7.sentence-2)
These evaluations are
sequenced before
the evaluation of the precondition assertions of the function,
which are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#expr.call-7.sentence-3)
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[.](#expr.call-7.sentence-4)
[*Note [7](#expr.call-note-7)*:
All side effects of
argument evaluations are sequenced before the function is
entered (see [[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.call-7.sentence-5)
— *end note*]
[*Example [3](#expr.call-example-3)*: 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 example*]
[*Note [8](#expr.call-note-8)*:
If an operator function is invoked
using operator notation,
argument evaluation is sequenced
as specified for the built-in operator;
see [[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions")[.](#expr.call-7.sentence-6)
— *end note*]
[*Example [4](#expr.call-example-4)*: 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);
After performing the initializations,
the value of i is 2 (see [[expr.shift]](#expr.shift "7.6.7Shift operators")),
but it is unspecified whether the value of j is 1 or 2[.](#expr.call-7.sentence-7)
— *end example*]
[8](#expr.call-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3948)
The result of a function call is the result of the possibly-converted operand
of the return statement ([[stmt.return]](stmt.return "8.8.4The return statement"))
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[.](#expr.call-8.sentence-1)
[9](#expr.call-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3957)
When the called function exits normally ([[stmt.return]](stmt.return "8.8.4The return statement"), [[expr.await]](#expr.await "7.6.2.4Await")),
all postcondition assertions of the function
are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#expr.call-9.sentence-1)
If the implementation introduces any temporary objects
to hold the result value as specified in [[class.temporary]](class.temporary "6.8.7Temporary objects"),
the evaluation of each postcondition assertion
is indeterminately sequenced with respect to
the initialization of any of those temporaries or the result object[.](#expr.call-9.sentence-2)
These evaluations, in turn, are sequenced before
the destruction of any function parameters[.](#expr.call-9.sentence-3)
[10](#expr.call-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3969)
[*Note [9](#expr.call-note-9)*:
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 ([[dcl.ref]](dcl.ref "9.3.4.3References")); if the reference is to
a const-qualified type, const_cast needs to be used to
cast away the constness in order to modify the argument's value[.](#expr.call-10.sentence-1)
Where a
parameter is of const reference type a temporary object is
introduced if
needed ([[dcl.type]](dcl.type "9.2.9Type specifiers"), [[lex.literal]](lex.literal "5.13Literals"), [[lex.string]](lex.string "5.13.5String literals"), [[dcl.array]](dcl.array "9.3.4.5Arrays"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#expr.call-10.sentence-2)
In addition, it is possible to modify the values of non-constant objects through
pointer parameters[.](#expr.call-10.sentence-3)
— *end note*]
[11](#expr.call-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3989)
A function can be declared to accept fewer arguments (by declaring [default
arguments](dcl.fct.default "9.3.4.7Default arguments[dcl.fct.default]")) or more arguments (by using the ellipsis,..., or a function parameter pack ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))) than the number of
parameters in the [function definition](dcl.fct.def "9.6Function definitions[dcl.fct.def]")[.](#expr.call-11.sentence-1)
[*Note [10](#expr.call-note-10)*:
This implies that, except where the ellipsis (...) or a function
parameter pack is used, a parameter is available for each argument[.](#expr.call-11.sentence-2)
— *end note*]
[12](#expr.call-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4001)
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 va_arg ([[support.runtime]](support.runtime "17.14Other runtime support"))[.](#expr.call-12.sentence-1)
[*Note [11](#expr.call-note-11)*:
This paragraph does not apply to arguments passed to a function parameter pack[.](#expr.call-12.sentence-2)
Function parameter packs are expanded during template instantiation ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")),
thus each such argument has a corresponding parameter when a function template
specialization is actually called[.](#expr.call-12.sentence-3)
— *end note*]
The[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions are
performed on the argument expression[.](#expr.call-12.sentence-4)
An argument that has type cv std::nullptr_t is converted
to type void* ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"))[.](#expr.call-12.sentence-5)
After these conversions, if the
argument does not have arithmetic, enumeration, pointer, pointer-to-member,
or class type, the program is ill-formed[.](#expr.call-12.sentence-6)
Passing a potentially-evaluated argument
of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")) or
of a class type ([[class]](class "11Classes")) having
an eligible non-trivial copy constructor ([[special]](special "11.4.4Special member functions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
an eligible non-trivial move constructor, or
a non-trivial destructor ([[class.dtor]](class.dtor "11.4.7Destructors")),
with no corresponding parameter, is conditionally-supported withimplementation-defined semantics[.](#expr.call-12.sentence-7)
If the argument has
integral or enumeration type that is subject to the [integral
promotions](conv.prom "7.3.7Integral promotions[conv.prom]"), or a floating-point type that is subject to the[floating-point promotion](conv.fpprom "7.3.8Floating-point promotion[conv.fpprom]"), the value of the argument is converted to the
promoted type before the call[.](#expr.call-12.sentence-8)
These promotions are referred to as
the [*default argument promotions*](#def:promotion,default_argument_promotion "7.6.1.3Function call[expr.call]")[.](#expr.call-12.sentence-9)
[13](#expr.call-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4035)
Recursive calls are permitted, except to the [main function](basic.start.main "6.10.3.1main function[basic.start.main]")[.](#expr.call-13.sentence-1)
[14](#expr.call-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4040)
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[.](#expr.call-14.sentence-1)
If it is a non-void prvalue,
the type of the function call expression shall be complete,
except as specified in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")[.](#expr.call-14.sentence-2)
#### [7.6.1.4](#expr.type.conv) Explicit type conversion (functional notation) [[expr.type.conv]](expr.type.conv)
[1](#expr.type.conv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4051)
A [](dcl.type.simple "9.2.9.3Simple type specifiers[dcl.type.simple]")[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") or[](temp.res "13.8Name resolution[temp.res]")[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") followed
by a parenthesized optional [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") or
by a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") (the initializer)
constructs a value of the specified type
given the initializer[.](#expr.type.conv-1.sentence-1)
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](over.match.class.deduct "12.2.2.9Class template argument deduction[over.match.class.deduct]") for the remainder of this subclause[.](#expr.type.conv-1.sentence-2)
Otherwise, if the type contains a placeholder type,
it is replaced by the type
determined by placeholder type deduction ([[dcl.type.auto.deduct]](dcl.type.auto.deduct "9.2.9.7.2Placeholder type deduction"))[.](#expr.type.conv-1.sentence-3)
Let T denote the resulting type[.](#expr.type.conv-1.sentence-4)
Then:
- [(1.1)](#expr.type.conv-1.1)
If the initializer is a parenthesized single expression,
the type conversion expression is equivalent
to the corresponding cast
expression ([[expr.cast]](#expr.cast "7.6.3Explicit type conversion (cast notation)"))[.](#expr.type.conv-1.1.sentence-1)
- [(1.2)](#expr.type.conv-1.2)
Otherwise, if T is cv void,
the initializer shall be () or {} (after pack expansion, if any), and
the expression is a prvalue of type void that performs no initialization[.](#expr.type.conv-1.2.sentence-1)
- [(1.3)](#expr.type.conv-1.3)
Otherwise, if T is a reference type,
the expression has the same effect as
direct-initializing an invented variable t of type T from
the initializer and then
using t as the result of the expression;
the result is an lvalue ifT is an lvalue reference type or
an rvalue reference to function type and
an xvalue otherwise[.](#expr.type.conv-1.3.sentence-1)
- [(1.4)](#expr.type.conv-1.4)
Otherwise,
the expression is a prvalue of type T whose result object is direct-initialized ([[dcl.init]](dcl.init "9.5Initializers"))
with the initializer[.](#expr.type.conv-1.4.sentence-1)
If the initializer is a parenthesized optional [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]"),T shall not be an array type[.](#expr.type.conv-1.sentence-6)
[*Example [1](#expr.type.conv-example-1)*: struct A {};void f(A&); // #1void 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 example*]
#### [7.6.1.5](#expr.ref) Class member access [[expr.ref]](expr.ref)
[1](#expr.ref-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4128)
A postfix expression followed by a dot . or an arrow ->,
optionally followed by the keywordtemplate, and then followed by an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"),
is a postfix expression[.](#expr.ref-1.sentence-1)
[*Note [1](#expr.ref-note-1)*:
If the keyword template is used and
followed by an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"),
the unqualified name
is considered to refer to a template ([[temp.names]](temp.names "13.3Names of template specializations"))[.](#expr.ref-1.sentence-2)
If a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") results and is followed by a ::,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#expr.ref-1.sentence-3)
— *end note*]
[2](#expr.ref-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4153)
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 ([[expr.context]](expr.context "7.2.3Context dependence"));
if the expression after the dot designates a non-static data member,
the first expression shall be a glvalue[.](#expr.ref-2.sentence-1)
A postfix expression that is followed by an arrow
shall be a prvalue having pointer type[.](#expr.ref-2.sentence-2)
The expression E1->E2 is
converted to the equivalent form (*(E1)).E2; the remainder of[[expr.ref]](#expr.ref "7.6.1.5Class member access") will address only the form using a dot[.](#expr.ref-2.sentence-3)[49](#footnote-49 "Note that (*(E1)) is an lvalue.")
[3](#expr.ref-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4170)
The postfix expression before the dot is evaluated;[50](#footnote-50 "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 id-expression denotes a static member.") the result of that evaluation,
together with
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"),
determines the result of the entire postfix expression[.](#expr.ref-3.sentence-1)
[4](#expr.ref-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4184)
Abbreviating[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]").[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]").[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") as E1.E2, E1 is called the [*object expression*](#def:object_expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")[.](#expr.ref-4.sentence-1)
If the object expression is of scalar type,E2 shall name the pseudo-destructor
of that same type (ignoring cv-qualifications) andE1.E2 is a prvalue of type “function of () returning void”[.](#expr.ref-4.sentence-2)
[*Note [2](#expr.ref-note-2)*:
This value can only be used
for a notional function call ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5Destruction"))[.](#expr.ref-4.sentence-3)
— *end note*]
[5](#expr.ref-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4198)
Otherwise, the object expression shall be of class type[.](#expr.ref-5.sentence-1)
The class type shall be complete
unless the class member access appears in the definition of that class[.](#expr.ref-5.sentence-2)
[*Note [3](#expr.ref-note-3)*:
The program is ill-formed if the result differs from that
when the class is complete ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#expr.ref-5.sentence-3)
— *end note*]
[*Note [4](#expr.ref-note-4)*:
[[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup") describes how names are looked up after the. and -> operators[.](#expr.ref-5.sentence-4)
— *end note*]
[6](#expr.ref-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4211)
If E2 is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"),
then let T1 be the type of E1[.](#expr.ref-6.sentence-1)
E2 shall designate either
a member of T1 or
a direct base class relationship (T1, B)[.](#expr.ref-6.sentence-2)
[7](#expr.ref-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4218)
If E2 designates a bit-field, E1.E2 is a bit-field[.](#expr.ref-7.sentence-1)
The
type and value category of E1.E2 are determined as follows[.](#expr.ref-7.sentence-2)
In the remainder of [[expr.ref]](#expr.ref "7.6.1.5Class member access"), *cq* represents eitherconst or the absence of const and *vq* represents
either volatile or the absence of volatile[.](#expr.ref-7.sentence-3)
*cv* represents an arbitrary set of cv-qualifiers, as defined
in [[basic.type.qualifier]](basic.type.qualifier "6.9.5CV-qualifiers")[.](#expr.ref-7.sentence-4)
[8](#expr.ref-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4227)
If E2 designates an entity
that is declared to have type “reference to T”, thenE1.E2 is an lvalue of type T[.](#expr.ref-8.sentence-1)
In that case, if E2 designates a static data member,E1.E2 designates the object or function to which
the reference is bound,
otherwise E1.E2 designates the object or function to which
the corresponding reference member of E1 is bound[.](#expr.ref-8.sentence-2)
Otherwise, one of the following rules applies[.](#expr.ref-8.sentence-3)
- [(8.1)](#expr.ref-8.1)
If E2 designates a static data member and the type of E2 is T, then E1.E2 is an lvalue; the expression designates
the named member of the class[.](#expr.ref-8.1.sentence-1)
The type of E1.E2 is T[.](#expr.ref-8.1.sentence-2)
- [(8.2)](#expr.ref-8.2)
Otherwise, if E2 designates a non-static data member and the type ofE1 is “*cq1 vq1* X”, and the type of E2 is “*cq2 vq2* T”, the expression designates the corresponding
member subobject of the object designated by E1[.](#expr.ref-8.2.sentence-1)
If E1 is an lvalue, then E1.E2 is an lvalue;
otherwise E1.E2 is an xvalue[.](#expr.ref-8.2.sentence-2)
Let the notation *vq12* stand for the “union” of*vq1* and *vq2*; that is, if *vq1* or *vq2* is volatile, then *vq12* is volatile[.](#expr.ref-8.2.sentence-3)
Similarly,
let the notation *cq12* stand for the “union” of *cq1* and *cq2*; that is, if *cq1* or *cq2* isconst, then *cq12* is const[.](#expr.ref-8.2.sentence-4)
If the entity designated by E2 is declared to be a mutable member,
then the type of E1.E2 is “*vq12* T”[.](#expr.ref-8.2.sentence-5)
If the entity designated by E2 is not declared to be a mutable member,
then the type of E1.E2 is “*cq12* *vq12*€[.](#expr.ref-8.2.sentence-6)
- [(8.3)](#expr.ref-8.3)
Otherwise, if E2 denotes an overload set,
the expression shall be the (possibly-parenthesized) left-hand operand of
a member function call ([[expr.call]](#expr.call "7.6.1.3Function call")), and
function overload resolution ([[over.match]](over.match "12.2Overload resolution"))
is used to select the function to which E2 refers[.](#expr.ref-8.3.sentence-1)
The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2[.](#expr.ref-8.3.sentence-2)
* [(8.3.1)](#expr.ref-8.3.1)
If E2 refers to a static member function,E1.E2 is an lvalue[.](#expr.ref-8.3.1.sentence-1)
* [(8.3.2)](#expr.ref-8.3.2)
Otherwise (when E2 refers to a non-static member function),E1.E2 is a prvalue[.](#expr.ref-8.3.2.sentence-1)
[*Note [5](#expr.ref-note-5)*:
Any redundant set of parentheses surrounding the expression
is ignored ([[expr.prim.paren]](expr.prim.paren "7.5.4Parentheses"))[.](#expr.ref-8.3.2.sentence-2)
— *end note*]
- [(8.4)](#expr.ref-8.4)
Otherwise, if E2 designates a nested type,
the expression E1.E2 is ill-formed[.](#expr.ref-8.4.sentence-1)
- [(8.5)](#expr.ref-8.5)
Otherwise, if E2 designates a member enumerator and the type of E2 is T, the expression E1.E2 is a prvalue of type T whose value is the value of the enumerator[.](#expr.ref-8.5.sentence-1)
- [(8.6)](#expr.ref-8.6)
Otherwise, if E2 designates a direct base class relationship (D,B) and the type of E1 is cv T,
the expression designates the direct base class subobject of type B of the object designated by E1[.](#expr.ref-8.6.sentence-1)
If E1 is an lvalue,
then E1.E2 is an lvalue;
otherwise, E1.E2 is an xvalue[.](#expr.ref-8.6.sentence-2)
The type of E1.E2 is “cv B”[.](#expr.ref-8.6.sentence-3)
[*Note [6](#expr.ref-note-6)*:
This can only occur in an expression of the form e1.[:e2:][.](#expr.ref-8.6.sentence-4)
— *end note*]
[*Example [1](#expr.ref-example-1)*: struct B {int b;};struct C : B {int get() const { return b; }};struct D : B, C { };
constexpr int f() { D d = {1, {}}; // b unambiguously refers to the direct base class of type B,// not the indirect base class of type 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 example*]
- [(8.7)](#expr.ref-8.7)
Otherwise, the program is ill-formed[.](#expr.ref-8.7.sentence-1)
[9](#expr.ref-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4332)
If E2 designates a non-static member
(possibly after overload resolution),
the program is ill-formed if the class of which E2 designates
a direct member is an ambiguous base ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) of
the designating class ([[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")) of E2[.](#expr.ref-9.sentence-1)
[*Note [7](#expr.ref-note-7)*:
The program is also ill-formed if the naming class is an ambiguous base of the class type
of the object expression; see [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")[.](#expr.ref-9.sentence-2)
— *end note*]
[10](#expr.ref-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4343)
If E2 designates a non-static member
(possibly after overload resolution) and
the result of E1 is an object whose type
is not similar ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) to the type of E1,
the behavior is undefined[.](#expr.ref-10.sentence-1)
[*Example [2](#expr.ref-example-2)*: 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 B subobject of dreinterpret_cast<B&>(d).j; // undefined behavior} — *end example*]
[49)](#footnote-49)[49)](#footnoteref-49)
Note that(*(E1)) is an lvalue[.](#footnote-49.sentence-1)
[50)](#footnote-50)[50)](#footnoteref-50)
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[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denotes a static member[.](#footnote-50.sentence-1)
#### [7.6.1.6](#expr.post.incr) Increment and decrement [[expr.post.incr]](expr.post.incr)
[1](#expr.post.incr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4364)
The value of a postfix ++ expression is the value obtained by
applying the lvalue-to-rvalue conversion ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")) to its operand[.](#expr.post.incr-1.sentence-1)
[*Note [1](#expr.post.incr-note-1)*:
The value obtained is a copy of the original value[.](#expr.post.incr-1.sentence-2)
— *end note*]
The operand shall be a modifiable lvalue[.](#expr.post.incr-1.sentence-3)
The type of the operand shall
be an arithmetic type other than cv bool,
or a pointer to a complete object type[.](#expr.post.incr-1.sentence-4)
An operand with volatile-qualified type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types")[.](#expr.post.incr-1.sentence-5)
The value of the operand object is modified ([[defns.access]](defns.access "3.1access"))
as if it were the operand of the prefix ++ operator ([[expr.pre.incr]](#expr.pre.incr "7.6.2.3Increment and decrement"))[.](#expr.post.incr-1.sentence-6)
Thevalue computation of the ++ expression is sequenced before the
modification of the operand object[.](#expr.post.incr-1.sentence-7)
With respect to an
indeterminately-sequenced function call, the operation of postfix++ is
a single evaluation[.](#expr.post.incr-1.sentence-8)
[*Note [2](#expr.post.incr-note-2)*:
Therefore, a function call cannot intervene between the
lvalue-to-rvalue conversion and the side effect associated with any
single postfix ++ operator[.](#expr.post.incr-1.sentence-9)
— *end note*]
The result is a prvalue[.](#expr.post.incr-1.sentence-10)
The type of the result is the cv-unqualified
version of the type of the operand[.](#expr.post.incr-1.sentence-11)
[2](#expr.post.incr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4396)
The operand of postfix -- is decremented analogously to the
postfix ++ operator[.](#expr.post.incr-2.sentence-1)
[*Note [3](#expr.post.incr-note-3)*:
For prefix increment and decrement, see [[expr.pre.incr]](#expr.pre.incr "7.6.2.3Increment and decrement")[.](#expr.post.incr-2.sentence-2)
— *end note*]
#### [7.6.1.7](#expr.dynamic.cast) Dynamic cast [[expr.dynamic.cast]](expr.dynamic.cast)
[1](#expr.dynamic.cast-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4409)
The result of the expression dynamic_cast<T>(v) is the result of
converting the expression v to type T[.](#expr.dynamic.cast-1.sentence-1)
T shall be a pointer or reference to a complete class type, or
“pointer to cv void”[.](#expr.dynamic.cast-1.sentence-2)
The dynamic_cast operator shall not cast
away constness ([[expr.const.cast]](#expr.const.cast "7.6.1.11Const cast"))[.](#expr.dynamic.cast-1.sentence-3)
[2](#expr.dynamic.cast-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4419)
If T is a pointer type, v shall be a prvalue of a
pointer to complete class type, and the result is a prvalue of typeT[.](#expr.dynamic.cast-2.sentence-1)
If T is an lvalue reference type, v shall be
an lvalue of a complete class type, and the result is an lvalue of the
type referred to by T[.](#expr.dynamic.cast-2.sentence-2)
If T is an rvalue reference type,v shall be a glvalue having a complete class type, and the
result is an xvalue of the type referred to by T[.](#expr.dynamic.cast-2.sentence-3)
[3](#expr.dynamic.cast-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4428)
If the type of v is the same as T (ignoring cv-qualifications),
the result isv (converted if necessary)[.](#expr.dynamic.cast-3.sentence-1)
[4](#expr.dynamic.cast-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4433)
If T is “pointer to *cv1*€ and v has
type “pointer to *cv2*€ such that B is a base
class of D, the result is a pointer to the unique B subobject of the D object pointed to by v, or
a null pointer value if v is a null pointer value[.](#expr.dynamic.cast-4.sentence-1)
Similarly, ifT is “reference to *cv1*€ and v has
type *cv2* D such that B is a base class ofD, the result is the unique B subobject of the D object referred to by v[.](#expr.dynamic.cast-4.sentence-2)[51](#footnote-51 "The most derived object ([intro.object]) pointed or referred to by v can contain other B objects as base classes, but these are ignored.")
In both the pointer and
reference cases, the program is ill-formed if B is an inaccessible or
ambiguous base class of D[.](#expr.dynamic.cast-4.sentence-3)
[*Example [1](#expr.dynamic.cast-example-1)*: struct B { };struct D : B { };void foo(D* dp) { B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;} — *end example*]
[5](#expr.dynamic.cast-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4463)
Otherwise, v shall be a pointer to or a glvalue of a[polymorphic type](class.virtual#def:class,polymorphic "11.7.3Virtual functions[class.virtual]")[.](#expr.dynamic.cast-5.sentence-1)
[6](#expr.dynamic.cast-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4467)
If v is a null pointer value, the result is a null pointer value[.](#expr.dynamic.cast-6.sentence-1)
[7](#expr.dynamic.cast-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4470)
If v has type “pointer to cv U” andv does not point to an object
whose type is similar ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) to U and
that is
within its lifetime or
within its period of construction or destruction ([[class.cdtor]](class.cdtor "11.9.5Construction and destruction")),
the behavior is undefined[.](#expr.dynamic.cast-7.sentence-1)
If v is a glvalue of type U andv does not refer to an object
whose type is similar to U and
that is
within its lifetime or
within its period of construction or destruction,
the behavior is undefined[.](#expr.dynamic.cast-7.sentence-2)
[8](#expr.dynamic.cast-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4486)
If T is “pointer to cv void”, then the result
is a pointer to the most derived object pointed to by v[.](#expr.dynamic.cast-8.sentence-1)
Otherwise, a runtime check is applied to see if the object pointed or
referred to by v can be converted to the type pointed or
referred to by T[.](#expr.dynamic.cast-8.sentence-2)
[9](#expr.dynamic.cast-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4493)
Let C be the class type to which T points or refers[.](#expr.dynamic.cast-9.sentence-1)
The runtime
check logically executes as follows:
- [(9.1)](#expr.dynamic.cast-9.1)
If, in the most derived object pointed (referred) to by v,v points (refers) to a public base class subobject of aC object, and if only one object of type C is derived
from the subobject pointed (referred) to by v,
the result points (refers) to that C object[.](#expr.dynamic.cast-9.1.sentence-1)
- [(9.2)](#expr.dynamic.cast-9.2)
Otherwise, if 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 C, that is unambiguous
and public, the result points (refers) to theC subobject of the most derived object[.](#expr.dynamic.cast-9.2.sentence-1)
- [(9.3)](#expr.dynamic.cast-9.3)
Otherwise, the
runtime check [*fails*](#def:fails)[.](#expr.dynamic.cast-9.3.sentence-1)
[10](#expr.dynamic.cast-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4513)
The value of a failed cast to pointer type is the null pointer value of
the required result type[.](#expr.dynamic.cast-10.sentence-1)
A failed cast to reference type [throws
an exception](except.throw "14.2Throwing an exception[except.throw]") of a type that would match a[handler](except.handle "14.4Handling an exception[except.handle]") of type [std::bad_cast](bad.cast "17.7.4Class bad_­cast[bad.cast]")[.](#expr.dynamic.cast-10.sentence-2)
[*Example [2](#expr.dynamic.cast-example-2)*: 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 A D* dp = dynamic_cast<D*>(ap); // fails: yields null; f has two D subobjects E* ep = (E*)ap; // error: cast from virtual base E* ep1 = dynamic_cast<E*>(ap); // succeeds} — *end example*]
[*Note [1](#expr.dynamic.cast-note-1)*:
Subclause [[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describes the behavior of a dynamic_cast applied to an object under construction or destruction[.](#expr.dynamic.cast-10.sentence-3)
— *end note*]
[51)](#footnote-51)[51)](#footnoteref-51)
The most derived
object ([[intro.object]](intro.object "6.8.2Object model")) pointed or referred to byv can contain other B objects as base classes, but these
are ignored[.](#footnote-51.sentence-1)
#### [7.6.1.8](#expr.typeid) Type identification [[expr.typeid]](expr.typeid)
[1](#expr.typeid-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4555)
The result of a typeid expression is an lvalue of static typeconst std::type_info ([[type.info]](type.info "17.7.3Class type_­info")) and dynamic type conststd::type_info or const *name* where *name* is animplementation-defined class publicly derived fromstd::type_info which preserves the behavior described
in [[type.info]](type.info "17.7.3Class type_­info")[.](#expr.typeid-1.sentence-1)[52](#footnote-52 "The recommended name for such a class is extended_­type_­info.")
The lifetime of the object referred to by the lvalue extends to the end
of the program[.](#expr.typeid-1.sentence-2)
Whether or not the destructor is called for thestd::type_info object at the end of the program is unspecified[.](#expr.typeid-1.sentence-3)
[2](#expr.typeid-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4574)
If the type of the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") or [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") operand is
a (possibly cv-qualified) class type or
a reference to (possibly cv-qualified) class type,
that class shall be completely defined[.](#expr.typeid-2.sentence-1)
[3](#expr.typeid-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4580)
If an [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") operand of typeid is
a possibly-parenthesized [*unary-expression*](#nt:unary-expression "7.6.2.1General[expr.unary.general]") whose [*unary-operator*](#nt:unary-operator "7.6.2.1General[expr.unary.general]") is * and
whose operand evaluates to a null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")),
the typeid expression throws an exception ([[except.throw]](except.throw "14.2Throwing an exception"))
of a type that would match a handler of typestd::bad_typeid ([[bad.typeid]](bad.typeid "17.7.5Class bad_­typeid"))[.](#expr.typeid-3.sentence-1)
[*Note [1](#expr.typeid-note-1)*:
In other contexts, evaluating such a [*unary-expression*](#nt:unary-expression "7.6.2.1General[expr.unary.general]") results in undefined behavior ([[expr.unary.op]](#expr.unary.op "7.6.2.2Unary operators"))[.](#expr.typeid-3.sentence-2)
— *end note*]
[4](#expr.typeid-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4595)
When typeid is applied to a glvalue whose type is a
polymorphic class type ([[class.virtual]](class.virtual "11.7.3Virtual functions")), the result refers to astd::type_info object representing the type of the most derived
object ([[intro.object]](intro.object "6.8.2Object model")) (that is, the dynamic type) to which the
glvalue refers[.](#expr.typeid-4.sentence-1)
[5](#expr.typeid-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4602)
When typeid is applied to an expression other than a glvalue of
a polymorphic class type, the result refers to a std::type_info object representing the static type of the expression[.](#expr.typeid-5.sentence-1)
[Lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") conversions are not applied to
the expression[.](#expr.typeid-5.sentence-2)
If the expression is a prvalue,
the [temporary materialization conversion](conv.rval "7.3.5Temporary materialization conversion[conv.rval]") is applied[.](#expr.typeid-5.sentence-3)
The expression is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]")[.](#expr.typeid-5.sentence-4)
[6](#expr.typeid-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4614)
When typeid is applied to a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"), the result
refers to a std::type_info object representing the type of the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#expr.typeid-6.sentence-1)
If the type of the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") is a reference
to a possibly cv-qualified type, the result of thetypeid expression refers to a std::type_info object
representing the cv-unqualified referenced type[.](#expr.typeid-6.sentence-2)
[*Note [2](#expr.typeid-note-2)*:
The [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") cannot denote a function type with
a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#expr.typeid-6.sentence-3)
— *end note*]
[7](#expr.typeid-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4626)
If the type of the expression or [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") is a
cv-qualified type, the result of the typeid expression refers
to a std::type_info object representing the cv-unqualified
type[.](#expr.typeid-7.sentence-1)
[*Example [1](#expr.typeid-example-1)*: class D { /* ... */ };
D d1;const D d2;
typeid(d1) == typeid(d2); // yields truetypeid(D) == typeid(const D); // yields truetypeid(D) == typeid(d2); // yields truetypeid(D) == typeid(const D&); // yields true — *end example*]
[8](#expr.typeid-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4644)
The type std::type_info ([[type.info]](type.info "17.7.3Class type_­info")) is not predefined;
if a standard library declaration ([[typeinfo.syn]](typeinfo.syn "17.7.2Header <typeinfo> synopsis"), [[std.modules]](std.modules "16.4.2.4Modules")) ofstd::type_info does not precede ([[basic.lookup.general]](basic.lookup.general "6.5.1General"))
a typeid expression, the program is ill-formed[.](#expr.typeid-8.sentence-1)
[9](#expr.typeid-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4650)
[*Note [3](#expr.typeid-note-3)*:
Subclause [[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describes the behavior of typeid applied to an object under construction or destruction[.](#expr.typeid-9.sentence-1)
— *end note*]
[52)](#footnote-52)[52)](#footnoteref-52)
The recommended name for such a class isextended_type_info[.](#footnote-52.sentence-1)
#### [7.6.1.9](#expr.static.cast) Static cast [[expr.static.cast]](expr.static.cast)
[1](#expr.static.cast-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4658)
The result of the expression static_cast<T>(v) is the result of
converting the expression v to type T[.](#expr.static.cast-1.sentence-1)
If T is an lvalue reference type
or an rvalue reference to function type, the result is an lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue[.](#expr.static.cast-1.sentence-2)
[2](#expr.static.cast-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4670)
An lvalue of type “*cv1* B”, where B is a class
type, can be cast to type “reference to *cv2*€, whereD is a complete class derived ([[class.derived]](class.derived "11.7Derived classes")) from B,
if *cv2* is the
same cv-qualification as, or greater cv-qualification than,*cv1*[.](#expr.static.cast-2.sentence-1)
If B is a virtual base class of D or a base class of a virtual base class of D,
or if no valid standard conversion from “pointer to D”
to “pointer to B” exists ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")), the program is ill-formed[.](#expr.static.cast-2.sentence-2)
An xvalue of type
“*cv1* B” can be cast to type “rvalue reference to*cv2* D” with the same constraints as for an lvalue of
type “*cv1* B”[.](#expr.static.cast-2.sentence-3)
If the object
of type “*cv1* B” is actually a base class subobject of an object
of type D, the result refers to the enclosing object of typeD[.](#expr.static.cast-2.sentence-4)
Otherwise, the behavior is undefined[.](#expr.static.cast-2.sentence-5)
[*Example [1](#expr.static.cast-example-1)*: struct B { };struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue denoting the original d object — *end example*]
[3](#expr.static.cast-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4700)
An lvalue
of type T1 can be cast to type “rvalue
reference to T2” if T2 is reference-compatible withT1 ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#expr.static.cast-3.sentence-1)
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](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]") is applied to the bit-field and the resulting prvalue is used as the
operand of the static_cast for the remainder of this subclause[.](#expr.static.cast-3.sentence-2)
If T2 is an inaccessible ([[class.access]](class.access "11.8Member access control")) or
ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) base class of T1,
a program that necessitates such a cast is ill-formed[.](#expr.static.cast-3.sentence-3)
[4](#expr.static.cast-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4713)
Any expression can be explicitly converted to type cv void,
in which case the operand is a discarded-value expression ([[expr.prop]](expr.prop "7.2Properties of expressions"))[.](#expr.static.cast-4.sentence-1)
[*Note [1](#expr.static.cast-note-1)*:
Such a static_cast has no result
as it is a prvalue of type void; see [[basic.lval]](basic.lval "7.2.1Value category")[.](#expr.static.cast-4.sentence-2)
— *end note*]
[*Note [2](#expr.static.cast-note-2)*:
However, if the value is in a temporary
object ([[class.temporary]](class.temporary "6.8.7Temporary objects")), 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[.](#expr.static.cast-4.sentence-3)
— *end note*]
[5](#expr.static.cast-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4728)
Otherwise, an expression E can be explicitly converted to a type T if there is an implicit conversion sequence ([[over.best.ics]](over.best.ics "12.2.4.2Implicit conversion sequences"))
from E to T,
if overload resolution for a direct-initialization ([[dcl.init]](dcl.init "9.5Initializers"))
of an object or reference of type T from E would find at least one viable function ([[over.match.viable]](over.match.viable "12.2.3Viable functions")), or
if T is an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))
having a first element x and
there is an implicit conversion sequence
from E to the type of x[.](#expr.static.cast-5.sentence-1)
If T is a reference type, the effect is
the same as performing the declaration and initializationT t(E); for some invented temporary variable t ([[dcl.init]](dcl.init "9.5Initializers"))
and then using the temporary variable as the result of the conversion[.](#expr.static.cast-5.sentence-2)
Otherwise, the result object is direct-initialized from E[.](#expr.static.cast-5.sentence-3)
[*Note [3](#expr.static.cast-note-3)*:
The conversion is ill-formed when attempting to convert an
expression of class type to an inaccessible or ambiguous base class[.](#expr.static.cast-5.sentence-4)
— *end note*]
[*Note [4](#expr.static.cast-note-4)*:
If T is “array of unknown bound of U”,
this direct-initialization defines the type of the expression as U[1][.](#expr.static.cast-5.sentence-5)
— *end note*]
[6](#expr.static.cast-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4756)
Otherwise, the lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")),
array-to-pointer ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")), and
function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion")) conversions are applied to the
operand, and the conversions that can be performed using static_cast are listed below[.](#expr.static.cast-6.sentence-1)
No other conversion can be performed using static_cast[.](#expr.static.cast-6.sentence-2)
[7](#expr.static.cast-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4763)
A value of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations"))
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[.](#expr.static.cast-7.sentence-1)
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[.](#expr.static.cast-7.sentence-2)
[8](#expr.static.cast-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4773)
A value of integral or enumeration type can be explicitly converted to
a complete enumeration type[.](#expr.static.cast-8.sentence-1)
If the enumeration type has a fixed underlying type,
the value is first converted to that type
by
integral promotion ([[conv.prom]](conv.prom "7.3.7Integral promotions")) or integral conversion ([[conv.integral]](conv.integral "7.3.9Integral conversions")),
if necessary, and
then to the enumeration type[.](#expr.static.cast-8.sentence-2)
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 ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")), and
otherwise, the behavior is undefined[.](#expr.static.cast-8.sentence-3)
A value of floating-point type can also be explicitly converted to an enumeration type[.](#expr.static.cast-8.sentence-4)
The resulting value is the same as converting the original value to the
underlying type of the enumeration ([[conv.fpint]](conv.fpint "7.3.11Floating-integral conversions")), and subsequently to
the enumeration type[.](#expr.static.cast-8.sentence-5)
[9](#expr.static.cast-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4794)
A prvalue of floating-point type can be explicitly converted to
any other floating-point type[.](#expr.static.cast-9.sentence-1)
If the source value can be exactly represented in the destination type,
the result of the conversion has that exact representation[.](#expr.static.cast-9.sentence-2)
If the source value is between two adjacent destination values,
the result of the conversion is
an implementation-defined choice of
either of those values[.](#expr.static.cast-9.sentence-3)
Otherwise, the behavior is undefined[.](#expr.static.cast-9.sentence-4)
[10](#expr.static.cast-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4805)
A prvalue of type “pointer to *cv1*€, where B is a class type, can be converted to a prvalue of type “pointer to*cv2* D”,
where D is a complete class[derived](class.derived "11.7Derived classes[class.derived]") from B,
if *cv2* is the same cv-qualification as,
or greater cv-qualification than, *cv1*[.](#expr.static.cast-10.sentence-1)
If B is a virtual base class of D or
a base class of a virtual base class of D, or
if no valid standard conversion from “pointer to D”
to “pointer to B” exists ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")), the program is ill-formed[.](#expr.static.cast-10.sentence-2)
The null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")) is converted
to the null pointer value of the destination type[.](#expr.static.cast-10.sentence-3)
If the prvalue of type
“pointer to *cv1*€ points to a B that is
actually a base class subobject of an object of type D, the resulting
pointer points to the enclosing object of type D[.](#expr.static.cast-10.sentence-4)
Otherwise, the
behavior is undefined[.](#expr.static.cast-10.sentence-5)
[11](#expr.static.cast-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4827)
A prvalue of type “pointer to member of D of type *cv1*T” can be converted to a prvalue of type “pointer to member ofB of type *cv2*€, whereD is a complete class type andB is a [base class](class.derived "11.7Derived classes[class.derived]") of D,
if *cv2* is the same cv-qualification
as, or greater cv-qualification than, *cv1*[.](#expr.static.cast-11.sentence-1)
[*Note [5](#expr.static.cast-note-5)*:
Function types (including those used in pointer-to-member-function types)
are never cv-qualified ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#expr.static.cast-11.sentence-2)
— *end note*]
If no valid standard conversion
from “pointer to member of B of type T”
to “pointer to member of D of type T”
exists ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions")), the program is ill-formed[.](#expr.static.cast-11.sentence-3)
The [null member pointer value](conv.mem#def:value,null_member_pointer "7.3.13Pointer-to-member conversions[conv.mem]") is converted to the null
member pointer value of the destination type[.](#expr.static.cast-11.sentence-4)
If class 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[.](#expr.static.cast-11.sentence-5)
Otherwise, the behavior is undefined[.](#expr.static.cast-11.sentence-6)
[*Note [6](#expr.static.cast-note-6)*:
Although class 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 [[expr.mptr.oper]](#expr.mptr.oper "7.6.4Pointer-to-member operators")[.](#expr.static.cast-11.sentence-7)
— *end note*]
[12](#expr.static.cast-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4856)
A prvalue of type “pointer to *cv1* void” can be
converted to a prvalue of type “pointer to *cv2*€,
where T is an object type and *cv2* is the same
cv-qualification as, or greater cv-qualification than, *cv1*[.](#expr.static.cast-12.sentence-1)
If the original pointer value represents the addressA of a byte in memory andA does not satisfy the alignment requirement of T,
then the resulting pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")) is unspecified[.](#expr.static.cast-12.sentence-2)
Otherwise, if the original pointer value points to an object *a*,
and there is an object *b* of type similar to T that is [pointer-interconvertible](basic.compound#def:pointer-interconvertible "6.9.4Compound types[basic.compound]") with *a*,
the result is a pointer to *b*[.](#expr.static.cast-12.sentence-3)
Otherwise, the pointer value is unchanged by the conversion[.](#expr.static.cast-12.sentence-4)
[*Example [2](#expr.static.cast-example-2)*: T* p1 = new T;const T* p2 = static_cast<const T*>(static_cast<void*>(p1));bool b = p1 == p2; // b will have the value true. — *end example*]
#### [7.6.1.10](#expr.reinterpret.cast) Reinterpret cast [[expr.reinterpret.cast]](expr.reinterpret.cast)
[1](#expr.reinterpret.cast-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4880)
The result of the expression reinterpret_cast<T>(v) is the
result of converting the expression v to type T[.](#expr.reinterpret.cast-1.sentence-1)
If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions are
performed on the expression v[.](#expr.reinterpret.cast-1.sentence-2)
Conversions that can be performed explicitly
using reinterpret_cast are listed below[.](#expr.reinterpret.cast-1.sentence-3)
No other conversion can
be performed explicitly using reinterpret_cast[.](#expr.reinterpret.cast-1.sentence-4)
[2](#expr.reinterpret.cast-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4896)
The reinterpret_cast operator shall not cast away constness ([[expr.const.cast]](#expr.const.cast "7.6.1.11Const cast"))[.](#expr.reinterpret.cast-2.sentence-1)
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[.](#expr.reinterpret.cast-2.sentence-2)
[3](#expr.reinterpret.cast-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4902)
[*Note [1](#expr.reinterpret.cast-note-1)*:
The mapping performed by reinterpret_cast might, or might not, produce a
representation different from the original value[.](#expr.reinterpret.cast-3.sentence-1)
— *end note*]
[4](#expr.reinterpret.cast-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4908)
A pointer can be explicitly converted to any integral type large enough
to hold all values of its type[.](#expr.reinterpret.cast-4.sentence-1)
The mapping function is implementation-defined[.](#expr.reinterpret.cast-4.sentence-2)
[*Note [2](#expr.reinterpret.cast-note-2)*:
It is intended to be unsurprising to those who know the addressing
structure of the underlying machine[.](#expr.reinterpret.cast-4.sentence-3)
— *end note*]
A value of type std::nullptr_t can be converted to an integral
type; the conversion has the same meaning and validity as a conversion of(void*)0 to the integral type[.](#expr.reinterpret.cast-4.sentence-4)
[*Note [3](#expr.reinterpret.cast-note-3)*:
A reinterpret_cast cannot be used to convert a value of any type to the typestd::nullptr_t[.](#expr.reinterpret.cast-4.sentence-5)
— *end note*]
[5](#expr.reinterpret.cast-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4928)
A value of integral type or enumeration type can be explicitly converted
to a pointer[.](#expr.reinterpret.cast-5.sentence-1)
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 ([[basic.compound]](basic.compound "6.9.4Compound types"));mappings between pointers and integers are otherwiseimplementation-defined[.](#expr.reinterpret.cast-5.sentence-2)
[6](#expr.reinterpret.cast-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4939)
A function pointer can be explicitly converted
to a function pointer of a different type[.](#expr.reinterpret.cast-6.sentence-1)
[*Note [4](#expr.reinterpret.cast-note-4)*:
The effect of calling a function through a pointer to a function
type ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) that is not the same as the type used in the
definition of the function is undefined ([[expr.call]](#expr.call "7.6.1.3Function call"))[.](#expr.reinterpret.cast-6.sentence-2)
— *end note*]
Except that converting
a prvalue of type “pointer to T1” to the type “pointer toT2” (where T1 and T2 are function types) and
back to its original type yields the original pointer value, the result
of such a pointer conversion is unspecified[.](#expr.reinterpret.cast-6.sentence-3)
[7](#expr.reinterpret.cast-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4957)
An object pointer
can be explicitly converted to an object pointer of a different type[.](#expr.reinterpret.cast-7.sentence-1)[53](#footnote-53 "The types can have different cv-qualifiers, subject to the overall restriction that a reinterpret_­cast cannot cast away constness.")
When a prvalue v of object pointer type is converted to
the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v))[.](#expr.reinterpret.cast-7.sentence-2)
[*Note [5](#expr.reinterpret.cast-note-5)*:
Converting a pointer of type “pointer to T1”
that points to an object of type T1 to the type “pointer to T2”
(where T2 is an object type
and the alignment requirements of T2 are no stricter than those of T1)
and back to its original type yields the original pointer value[.](#expr.reinterpret.cast-7.sentence-3)
— *end note*]
[8](#expr.reinterpret.cast-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4978)
Converting a function pointer to an object pointer
type or vice versa is
conditionally-supported[.](#expr.reinterpret.cast-8.sentence-1)
The meaning of such a conversion isimplementation-defined,
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[.](#expr.reinterpret.cast-8.sentence-2)
[9](#expr.reinterpret.cast-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4988)
The null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")) is converted to the null pointer value
of the destination type[.](#expr.reinterpret.cast-9.sentence-1)
[*Note [6](#expr.reinterpret.cast-note-6)*:
A null pointer constant of type 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[.](#expr.reinterpret.cast-9.sentence-2)
— *end note*]
[10](#expr.reinterpret.cast-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4997)
A prvalue of type “pointer to member of X of type T1”
can be explicitly converted to a prvalue of a different type “pointer to member ofY of type T2” if T1 and T2 are both
function types or both object types[.](#expr.reinterpret.cast-10.sentence-1)[54](#footnote-54 "T1 and T2 can have different cv-qualifiers, subject to the overall restriction that a reinterpret_­cast cannot cast away constness.")
The null member pointer value ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions")) is converted to the
null member pointer value of the destination type[.](#expr.reinterpret.cast-10.sentence-2)
The result of this
conversion is unspecified, except in the following cases:
- [(10.1)](#expr.reinterpret.cast-10.1)
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[.](#expr.reinterpret.cast-10.1.sentence-1)
- [(10.2)](#expr.reinterpret.cast-10.2)
Converting a prvalue of type “pointer to data member of X of type T1” to the type “pointer to data member of Y of type T2” (where the alignment requirements of T2 are
no stricter than those of T1) and back to its original type
yields the original pointer-to-member value[.](#expr.reinterpret.cast-10.2.sentence-1)
[11](#expr.reinterpret.cast-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5025)
If v is a glvalue of type T1,
designating an object or function *x*,
it can be cast to the type “reference to T2”
if an expression of type “pointer to T1”
can be explicitly converted to the type “pointer to T2”
using a reinterpret_cast[.](#expr.reinterpret.cast-11.sentence-1)
The result is that of *reinterpret_cast<T2 *>(p) where p is a pointer to *x* of type “pointer to T1”[.](#expr.reinterpret.cast-11.sentence-2)
[*Note [7](#expr.reinterpret.cast-note-7)*:
No temporary is materialized ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) or created,
no copy is made, and
no constructors ([[class.ctor]](class.ctor "11.4.5Constructors")) or conversion
functions ([[class.conv]](class.conv "11.4.8Conversions")) are called[.](#expr.reinterpret.cast-11.sentence-3)[55](#footnote-55 "This is sometimes referred to as a type pun when the result refers to the same object as the source glvalue.")
— *end note*]
[53)](#footnote-53)[53)](#footnoteref-53)
The
types can have different cv-qualifiers, subject to
the overall
restriction that a reinterpret_cast cannot cast away constness[.](#footnote-53.sentence-1)
[54)](#footnote-54)[54)](#footnoteref-54)
T1 and T2 can have
different cv-qualifiers, subject to
the overall restriction that a reinterpret_cast cannot cast away
constness[.](#footnote-54.sentence-1)
[55)](#footnote-55)[55)](#footnoteref-55)
This is sometimes referred to as a type pun
when the result refers to the same object as the source glvalue[.](#footnote-55.sentence-1)
#### [7.6.1.11](#expr.const.cast) Const cast [[expr.const.cast]](expr.const.cast)
[1](#expr.const.cast-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5051)
The result of the expression const_cast<T>(v) is of typeT[.](#expr.const.cast-1.sentence-1)
If T is an lvalue reference to object type, the result is an
lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions are
performed on the expression v[.](#expr.const.cast-1.sentence-2)
The [temporary materialization conversion](conv.rval "7.3.5Temporary materialization conversion[conv.rval]") is not
performed on v, other than as specified below[.](#expr.const.cast-1.sentence-3)
Conversions that can be performed explicitly usingconst_cast are listed below[.](#expr.const.cast-1.sentence-4)
No other conversion shall be
performed explicitly using const_cast[.](#expr.const.cast-1.sentence-5)
[2](#expr.const.cast-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5068)
[*Note [1](#expr.const.cast-note-1)*:
Subject to the restrictions in this subclause, an expression can be cast
to its own type using a const_cast operator[.](#expr.const.cast-2.sentence-1)
— *end note*]
[3](#expr.const.cast-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5074)
For two similar object pointer or pointer to data member typesT1 and T2 ([[conv.qual]](conv.qual "7.3.6Qualification conversions")),
a prvalue of type T1 can be explicitly
converted to the type T2 using a const_cast if, considering the qualification-decompositions of both types,
each P1i is the same as P2i for all i[.](#expr.const.cast-3.sentence-1)
If v is a null pointer or null member pointer,
the result is a null pointer or null member pointer, respectively[.](#expr.const.cast-3.sentence-2)
Otherwise, the result points to or past the end of the same object, or
points to the same member, respectively, as v[.](#expr.const.cast-3.sentence-3)
[4](#expr.const.cast-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5086)
For two object types T1 and T2, if a pointer to T1 can
be explicitly converted to the type “pointer to T2” using aconst_cast, then the following conversions can also be made:
- [(4.1)](#expr.const.cast-4.1)
an lvalue of type T1 can be explicitly converted to an lvalue
of type T2 using the cast const_cast<T2&>;
- [(4.2)](#expr.const.cast-4.2)
a glvalue of type T1 can be explicitly converted to an xvalue
of type T2 using the cast const_cast<T2&&>; and
- [(4.3)](#expr.const.cast-4.3)
if T1 is a class or array type,
a prvalue of type T1 can be
explicitly converted to an xvalue of type T2 using the castconst_cast<T2&&>[.](#expr.const.cast-4.sentence-1)
The temporary materialization conversion is performed on v[.](#expr.const.cast-4.3.sentence-2)
The result refers to the same object as the (possibly converted) operand[.](#expr.const.cast-4.sentence-2)
[*Example [1](#expr.const.cast-example-1)*: typedef int *A[3]; // array of 3 pointer to inttypedef const int *const CA[3]; // array of 3 const pointer to const intauto &&r2 = const_cast<A&&>(CA{}); // OK, temporary materialization conversion is performed — *end example*]
[5](#expr.const.cast-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5114)
[*Note [2](#expr.const.cast-note-2)*:
Depending on the type of the object, a write operation through the
pointer, lvalue or pointer to data member resulting from aconst_cast that casts away a const-qualifier[56](#footnote-56 "const_­cast is not limited to conversions that cast away a const-qualifier.") can produce undefined behavior ([[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers"))[.](#expr.const.cast-5.sentence-1)
— *end note*]
[6](#expr.const.cast-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5127)
A conversion from a type T1 to a type T2[*casts away constness*](#def:casting_away_constness "7.6.1.11Const cast[expr.const.cast]") if T1 and T2 are different,
there is a qualification-decomposition ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) of T1 yielding *n* such thatT2 has a qualification-decomposition of the formcv20 P20 cv21 P21 ⋯ cv2n−1 P2n−1 cv2n U2, and there is no qualification conversion that converts T1 tocv20 P10 cv21 P11 ⋯ cv2n−1 P1n−1 cv2n U1[.](#expr.const.cast-6.sentence-1)
[7](#expr.const.cast-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5143)
Casting from an lvalue of type T1 to an lvalue of typeT2 using an lvalue reference cast
or casting from an expression of type T1 to an xvalue of type T2 using
an rvalue reference cast
casts away constness if a cast from a prvalue of type “pointer to T1” to the type “pointer toT2” casts away constness[.](#expr.const.cast-7.sentence-1)
[8](#expr.const.cast-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5151)
[*Note [3](#expr.const.cast-note-3)*:
Some conversions which involve only changes in cv-qualification cannot
be done using const_cast[.](#expr.const.cast-8.sentence-1)
For instance, conversions between
pointers to functions are not covered because such conversions lead to
values whose use causes undefined behavior[.](#expr.const.cast-8.sentence-2)
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[.](#expr.const.cast-8.sentence-3)
— *end note*]
[56)](#footnote-56)[56)](#footnoteref-56)
const_cast is not limited to conversions that cast away a
const-qualifier[.](#footnote-56.sentence-1)
### [7.6.2](#expr.unary) Unary expressions [[expr.unary]](expr.unary)
#### [7.6.2.1](#expr.unary.general) General [[expr.unary.general]](expr.unary.general)
[1](#expr.unary.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5167)
Expressions with unary operators group right-to-left[.](#expr.unary.general-1.sentence-1)
[unary-expression:](#nt:unary-expression "7.6.2.1General[expr.unary.general]")
[*postfix-expression*](#nt:postfix-expression "7.6.1.1General[expr.post.general]")
[*unary-operator*](#nt:unary-operator "7.6.2.1General[expr.unary.general]") [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
++ [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
-- [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]")
sizeof [*unary-expression*](#nt:unary-expression "7.6.2.1General[expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
[*noexcept-expression*](#nt:noexcept-expression "7.6.2.7noexcept operator[expr.unary.noexcept]")
[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")
[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]")
[*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")
[unary-operator:](#nt:unary-operator "7.6.2.1General[expr.unary.general]") one of
* & + - ! ~
#### [7.6.2.2](#expr.unary.op) Unary operators [[expr.unary.op]](expr.unary.op)
[1](#expr.unary.op-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5219)
The unary * operator performs [*indirection*](#def:indirection "7.6.2.2Unary operators[expr.unary.op]")[.](#expr.unary.op-1.sentence-1)
Its operand shall be a prvalue of type “pointer to T”,
where T is an object or function type[.](#expr.unary.op-1.sentence-2)
The operator yields an lvalue of type T[.](#expr.unary.op-1.sentence-3)
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 [[expr.typeid]](#expr.typeid "7.6.1.8Type identification")[.](#expr.unary.op-1.sentence-4)
[*Note [1](#expr.unary.op-note-1)*:
Indirection through a pointer to an out-of-lifetime object is valid ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#expr.unary.op-1.sentence-5)
— *end note*]
[*Note [2](#expr.unary.op-note-2)*:
Indirection through a pointer to an incomplete type (other thancv void) is valid[.](#expr.unary.op-1.sentence-6)
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 [[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")[.](#expr.unary.op-1.sentence-7)
— *end note*]
[2](#expr.unary.op-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5241)
Each of the following unary operators yields a prvalue[.](#expr.unary.op-2.sentence-1)
[3](#expr.unary.op-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5244)
The operand of the unary & operator
shall be an lvalue of some type T[.](#expr.unary.op-3.sentence-1)
- [(3.1)](#expr.unary.op-3.1)
If the operand is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") designating a non-static member m,
other than an explicit object member function,m shall be a direct member of some class C that is not an anonymous union[.](#expr.unary.op-3.1.sentence-1)
The result has type “pointer to member of class C of type T”
and designates C::m[.](#expr.unary.op-3.1.sentence-2)
[*Note [3](#expr.unary.op-note-3)*:
A [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") that names a member of a namespace-scope anonymous union
is considered to be a class member access expression ([[expr.prim.id.general]](expr.prim.id.general "7.5.5.1General"))
and cannot be used to form a pointer to member[.](#expr.unary.op-3.1.sentence-3)
— *end note*]
- [(3.2)](#expr.unary.op-3.2)
Otherwise, the result has type “pointer to T” and points to
the designated object ([[intro.memory]](intro.memory "6.8.1Memory model")) or function ([[basic.compound]](basic.compound "6.9.4Compound types"))[.](#expr.unary.op-3.2.sentence-1)
If the operand designates an explicit object member function ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
the operand shall be
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")[.](#expr.unary.op-3.2.sentence-2)
[*Note [4](#expr.unary.op-note-4)*:
In particular, taking the address of a variable of type “cv T”
yields a pointer of type “pointer to cv T”[.](#expr.unary.op-3.2.sentence-3)
— *end note*]
[*Example [1](#expr.unary.op-example-1)*: struct A { int i; };struct B : A { };... &B::i ... // has type int A::*int a;int* p1 = &a;int* p2 = p1 + 1; // defined behaviorbool b = p2 > p1; // defined behavior, with value true — *end example*]
[*Note [5](#expr.unary.op-note-5)*:
A pointer to member formed from a mutable non-static data
member ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers")) does not reflect the mutable specifier
associated with the non-static data member[.](#expr.unary.op-3.sentence-2)
— *end note*]
[4](#expr.unary.op-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5292)
A pointer to member is only formed when an explicit & is used
and its operand is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") not enclosed in parentheses[.](#expr.unary.op-4.sentence-1)
[*Note [6](#expr.unary.op-note-6)*:
That is, the expression &(qualified-id), where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") is enclosed in parentheses, does not form an
expression of type “pointer to member”[.](#expr.unary.op-4.sentence-2)
Neither doesqualified-id, because there is no implicit conversion from a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") 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” ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion"))[.](#expr.unary.op-4.sentence-3)
Nor is&unqualified-id a pointer to member, even within the scope of
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")'s class[.](#expr.unary.op-4.sentence-4)
— *end note*]
[5](#expr.unary.op-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5309)
If & is applied to an lvalue of incomplete class type and the
complete type declares operator&(), it is unspecified whether
the operator has the built-in meaning or the operator function is
called[.](#expr.unary.op-5.sentence-1)
The operand of & shall not be a bit-field[.](#expr.unary.op-5.sentence-2)
[6](#expr.unary.op-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5315)
[*Note [7](#expr.unary.op-note-7)*:
The address of an overload set ([[over]](over "12Overloading")) can be taken
only in a context that uniquely determines
which function is referred to (see [[over.over]](over.over "12.3Address of an overload set"))[.](#expr.unary.op-6.sentence-1)
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”[.](#expr.unary.op-6.sentence-2)
— *end note*]
[7](#expr.unary.op-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5327)
The operand of the unary + operator shall be a prvalue of
arithmetic, unscoped
enumeration, or pointer type and the result is the value of the
argument[.](#expr.unary.op-7.sentence-1)
Integral promotion is performed on integral or enumeration
operands[.](#expr.unary.op-7.sentence-2)
The type of the result is the type of the promoted operand[.](#expr.unary.op-7.sentence-3)
[8](#expr.unary.op-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5335)
The operand of the unary - operator shall be a prvalue of
arithmetic or unscoped
enumeration type and the result is the negative of its operand[.](#expr.unary.op-8.sentence-1)
Integral
promotion is performed on integral or enumeration operands[.](#expr.unary.op-8.sentence-2)
The negative
of an unsigned quantity is computed by subtracting its value from 2n,
where n is the number of bits in the promoted operand[.](#expr.unary.op-8.sentence-3)
The type of the
result is the type of the promoted operand[.](#expr.unary.op-8.sentence-4)
[*Note [8](#expr.unary.op-note-8)*:
The result is the two's complement of the operand
(where operand and result are considered as unsigned)[.](#expr.unary.op-8.sentence-5)
— *end note*]
[9](#expr.unary.op-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5349)
The operand of the logical negation operator ! is contextually
converted to bool ([[conv]](conv "7.3Standard conversions"));
its value is true if the converted operand is false and false otherwise[.](#expr.unary.op-9.sentence-1)
The type of the result is bool[.](#expr.unary.op-9.sentence-2)
[10](#expr.unary.op-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5357)
The operand of the ~ operator shall be a prvalue of
integral or unscoped enumeration type[.](#expr.unary.op-10.sentence-1)
Integral promotions are performed[.](#expr.unary.op-10.sentence-2)
The type of the result is the type of the promoted operand[.](#expr.unary.op-10.sentence-3)
Given the coefficients xi of the base-2 representation ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
of the promoted operand x,
the coefficient ri of the base-2 representation of the result r is 1 if xi is 0, and 0 otherwise[.](#expr.unary.op-10.sentence-4)
[*Note [9](#expr.unary.op-note-9)*:
The result is the ones' complement of the operand
(where operand and result are considered as unsigned)[.](#expr.unary.op-10.sentence-5)
— *end note*]
There is an ambiguity
in the grammar when ~ is followed by
a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")[.](#expr.unary.op-10.sentence-6)
The ambiguity is resolved by treating ~ as the
operator rather than as the start of an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") naming a destructor[.](#expr.unary.op-10.sentence-7)
[*Note [10](#expr.unary.op-note-10)*:
Because the grammar does not permit an operator to follow the., ->, or :: tokens, a ~ followed by
a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") in a
member access expression or [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") is
unambiguously parsed as a destructor name[.](#expr.unary.op-10.sentence-8)
— *end note*]
#### [7.6.2.3](#expr.pre.incr) Increment and decrement [[expr.pre.incr]](expr.pre.incr)
[1](#expr.pre.incr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5390)
The operand of prefix ++ or -- shall not be of type cv bool[.](#expr.pre.incr-1.sentence-1)
An operand with volatile-qualified type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types")[.](#expr.pre.incr-1.sentence-2)
The expression ++x is otherwise equivalent to x+=1 and
the expression --x is otherwise equivalent to x-=1 ([[expr.assign]](#expr.assign "7.6.19Assignment and compound assignment operators"))[.](#expr.pre.incr-1.sentence-3)
[*Note [1](#expr.pre.incr-note-1)*:
For postfix increment and decrement, see [[expr.post.incr]](#expr.post.incr "7.6.1.6Increment and decrement")[.](#expr.pre.incr-1.sentence-4)
— *end note*]
#### [7.6.2.4](#expr.await) Await [[expr.await]](expr.await)
[1](#expr.await-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5411)
The co_await expression is used to suspend evaluation of a
coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions")) while awaiting completion of
the computation represented by the operand expression[.](#expr.await-1.sentence-1)
Suspending the evaluation of a coroutine
transfers control to its caller or resumer[.](#expr.await-1.sentence-2)
[await-expression:](#nt:await-expression "7.6.2.4Await[expr.await]")
co_await [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[2](#expr.await-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5423)
An [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") shall appear only as a potentially-evaluated
expression within the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") or [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"),
in either case
outside of a [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.pre]](except.pre "14.1Preamble"))[.](#expr.await-2.sentence-1)
In a [*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10Declaration statement[stmt.dcl]") or in the[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]") (if any)
of an [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]"), an [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") shall appear only in an [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") of that[*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10Declaration statement[stmt.dcl]") or [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]")[.](#expr.await-2.sentence-2)
An [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") shall not appear in a
default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#expr.await-2.sentence-3)
An [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") shall not appear in the initializer of
a block variable with static or thread storage duration[.](#expr.await-2.sentence-4)
An [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") shall not be
a potentially-evaluated subexpression
of the predicate of a contract assertion ([[basic.contract]](basic.contract "6.11Contract assertions"))[.](#expr.await-2.sentence-5)
A context within a function where an [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") can appear
is called a [*suspension context*](#def:suspension_context) of the function[.](#expr.await-2.sentence-6)
[3](#expr.await-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5444)
Evaluation of an [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") involves the following
auxiliary types, expressions, and objects:
- [(3.1)](#expr.await-3.1)
*p* is an lvalue naming the promise
object ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))
of the enclosing coroutine and P is the type of that object[.](#expr.await-3.1.sentence-1)
- [(3.2)](#expr.await-3.2)
Unless
the [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") was implicitly produced by
a [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") ([[expr.yield]](#expr.yield "7.6.17Yielding a value")),
an initial await expression,
or a final await expression ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions")),
a search is performed for the name await_transform in the scope of P ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#expr.await-3.2.sentence-1)
If this search is performed and finds at least one declaration,
then *a* is*p*.await_transform([*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]"));
otherwise, *a* is the [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")[.](#expr.await-3.2.sentence-2)
- [(3.3)](#expr.await-3.3)
*o* is determined by enumerating the applicableoperator co_await functions for an argument*a* ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions")), and choosing the best one through
overload resolution ([[over.match]](over.match "12.2Overload resolution"))[.](#expr.await-3.3.sentence-1)
If overload resolution is ambiguous,
the program is ill-formed[.](#expr.await-3.3.sentence-2)
If no viable functions are found, *o* is *a*[.](#expr.await-3.3.sentence-3)
Otherwise, *o* is a call to the selected function
with the argument *a*[.](#expr.await-3.3.sentence-4)
If *o* would be a prvalue,
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) is applied[.](#expr.await-3.3.sentence-5)
- [(3.4)](#expr.await-3.4)
*e* is an lvalue
referring to the result of evaluating
the (possibly-converted) *o*[.](#expr.await-3.4.sentence-1)
- [(3.5)](#expr.await-3.5)
*h* is an object of typestd::coroutine_handle<P> referring to the enclosing coroutine[.](#expr.await-3.5.sentence-1)
- [(3.6)](#expr.await-3.6)
*await-ready* is the expression*e*.await_ready(),
contextually converted to bool[.](#expr.await-3.6.sentence-1)
- [(3.7)](#expr.await-3.7)
*await-suspend* is the expression*e*.await_suspend(*h*),
which shall be a prvalue of type void, bool, orstd::coroutine_handle<Z> for some type Z[.](#expr.await-3.7.sentence-1)
- [(3.8)](#expr.await-3.8)
*await-resume* is the expression*e*.await_resume()[.](#expr.await-3.8.sentence-1)
[4](#expr.await-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5507)
The [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") has the same type and value category
as the *await-resume* expression[.](#expr.await-4.sentence-1)
[5](#expr.await-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5511)
The [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") evaluates
the (possibly-converted) *o* expression and
the *await-ready* expression, then:
- [(5.1)](#expr.await-5.1)
If the result of *await-ready* is false,
the coroutine is considered suspended[.](#expr.await-5.1.sentence-1)
Then:
* [(5.1.1)](#expr.await-5.1.1)
If the type of *await-suspend* is std::coroutine_handle<Z>,*await-suspend*.resume() is evaluated[.](#expr.await-5.1.1.sentence-1)
[*Note [1](#expr.await-note-1)*:
This resumes the coroutine referred to
by the result of *await-suspend*[.](#expr.await-5.1.1.sentence-2)
Any number of coroutines can be successively resumed in this fashion,
eventually returning control flow to the current coroutine caller or
resumer ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))[.](#expr.await-5.1.1.sentence-3)
— *end note*]
* [(5.1.2)](#expr.await-5.1.2)
Otherwise, if the type of *await-suspend* is bool,*await-suspend* is evaluated,
and the coroutine is resumed if the result is false[.](#expr.await-5.1.2.sentence-1)
* [(5.1.3)](#expr.await-5.1.3)
Otherwise, *await-suspend* is evaluated[.](#expr.await-5.1.3.sentence-1)
If the evaluation of *await-suspend* exits via an exception, the exception is caught,
the coroutine is resumed, and the exception is immediately
rethrown ([[except.throw]](except.throw "14.2Throwing an exception"))[.](#expr.await-5.1.sentence-3)
Otherwise, control flow returns
to the current coroutine caller or resumer ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))
without exiting any scopes ([[stmt.jump]](stmt.jump "8.8Jump statements"))[.](#expr.await-5.1.sentence-4)
The point in the coroutine
immediately prior to control returning to its caller or resumer
is a coroutine [*suspend point*](#def:suspend_point "7.6.2.4Await[expr.await]")[.](#expr.await-5.1.sentence-5)
- [(5.2)](#expr.await-5.2)
If the result of *await-ready* is true,
or when the coroutine is resumed
other than by rethrowing an exception from *await-suspend*,
the *await-resume* expression is evaluated, and
its result is the result of the [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]")[.](#expr.await-5.2.sentence-1)
[*Note [2](#expr.await-note-2)*:
With respect to sequencing,
an [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") is indivisible ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.await-5.sentence-2)
— *end note*]
[6](#expr.await-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5565)
[*Example [1](#expr.await-example-1)*: template <typename T>struct my_future {/* ... */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; /* ... */ 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) { /* ... */ }}; 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: [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") outside of function suspension contextint a[] = { co_await h() }; // error: [*await-expression*](#nt:await-expression "7.6.2.4Await[expr.await]") outside of function suspension context — *end example*]
#### [7.6.2.5](#expr.sizeof) Sizeof [[expr.sizeof]](expr.sizeof)
[1](#expr.sizeof-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5607)
The sizeof operator yields the number of bytes
occupied by a non-potentially-overlapping object of the type
of its operand[.](#expr.sizeof-1.sentence-1)
The operand is either an expression,
which is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]"), or a parenthesized[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#expr.sizeof-1.sentence-2)
The 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[.](#expr.sizeof-1.sentence-3)
The result of sizeof applied to any of the narrow character types is 1[.](#expr.sizeof-1.sentence-4)
The result ofsizeof applied to any other fundamental
type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types")) is implementation-defined[.](#expr.sizeof-1.sentence-5)
[*Note [1](#expr.sizeof-note-1)*:
In particular, the values of sizeof(bool), sizeof(char16_t),sizeof(char32_t), and sizeof(wchar_t) are
implementation-defined[.](#expr.sizeof-1.sentence-6)[57](#footnote-57 "sizeof(bool) is not required to be 1.")
— *end note*]
[*Note [2](#expr.sizeof-note-2)*:
See [[intro.memory]](intro.memory "6.8.1Memory model") for the definition of byte
and [[basic.types.general]](basic.types.general#term.object.representation "6.9.1General") for the definition of object representation[.](#expr.sizeof-1.sentence-7)
— *end note*]
[2](#expr.sizeof-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5641)
When applied to a reference type, the result is the size
of the referenced type[.](#expr.sizeof-2.sentence-1)
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[.](#expr.sizeof-2.sentence-2)
The result of applying sizeof to a
potentially-overlapping subobject is
the size of the type, not the size of the subobject[.](#expr.sizeof-2.sentence-3)[58](#footnote-58 "The actual size of a potentially-overlapping subobject can be less than the result of applying sizeof to the subobject, due to virtual base classes and less strict padding requirements on potentially-overlapping subobjects.")
When applied to an array, the result is the total number of bytes in the
array[.](#expr.sizeof-2.sentence-4)
This implies that the size of an array of n elements isn times the size of an element[.](#expr.sizeof-2.sentence-5)
[3](#expr.sizeof-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5663)
The lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")),
array-to-pointer ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")), and
function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion")) standard conversions are not
applied to the operand of sizeof[.](#expr.sizeof-3.sentence-1)
If the operand is a prvalue,
the [temporary materialization conversion](conv.rval "7.3.5Temporary materialization conversion[conv.rval]") is applied[.](#expr.sizeof-3.sentence-2)
[4](#expr.sizeof-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5672)
The [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in a sizeof... expression shall name a
pack[.](#expr.sizeof-4.sentence-1)
The sizeof... operator yields the number of elements
in the pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#expr.sizeof-4.sentence-2)
A sizeof... expression is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#expr.sizeof-4.sentence-3)
[*Example [1](#expr.sizeof-example-1)*: template<class... Types>struct count {static constexpr std::size_t value = sizeof...(Types);}; — *end example*]
[5](#expr.sizeof-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5686)
The result of sizeof and sizeof... is a prvalue of typestd::size_t[.](#expr.sizeof-5.sentence-1)
[*Note [3](#expr.sizeof-note-3)*:
A sizeof expression
is an integral constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#expr.sizeof-5.sentence-2)
The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") std::size_t is declared in the standard header[<cstddef>](cstddef.syn#header:%3ccstddef%3e "17.2.1Header <cstddef> synopsis[cstddef.syn]") ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis"), [[support.types.layout]](support.types.layout "17.2.4Sizes, alignments, and offsets"))[.](#expr.sizeof-5.sentence-3)
— *end note*]
[57)](#footnote-57)[57)](#footnoteref-57)
sizeof(bool) is not required to be 1[.](#footnote-57.sentence-1)
[58)](#footnote-58)[58)](#footnoteref-58)
The actual size of a potentially-overlapping subobject
can be less than the result of
applying sizeof to the subobject, due to virtual base classes
and less strict padding requirements on potentially-overlapping subobjects[.](#footnote-58.sentence-1)
#### [7.6.2.6](#expr.alignof) Alignof [[expr.alignof]](expr.alignof)
[1](#expr.alignof-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5700)
An alignof expression yields the alignment requirement
of its operand type[.](#expr.alignof-1.sentence-1)
The operand shall be a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") representing a complete object type, or an array thereof, or a reference
to one of those types[.](#expr.alignof-1.sentence-2)
[2](#expr.alignof-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5708)
The result is a prvalue of type std::size_t[.](#expr.alignof-2.sentence-1)
[*Note [1](#expr.alignof-note-1)*:
An alignof expression
is an integral constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#expr.alignof-2.sentence-2)
The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") std::size_t is declared in the standard header[<cstddef>](cstddef.syn#header:%3ccstddef%3e "17.2.1Header <cstddef> synopsis[cstddef.syn]") ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis"), [[support.types.layout]](support.types.layout "17.2.4Sizes, alignments, and offsets"))[.](#expr.alignof-2.sentence-3)
— *end note*]
[3](#expr.alignof-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5717)
When alignof is applied to a reference type, the result
is the alignment of the referenced type[.](#expr.alignof-3.sentence-1)
When alignof is applied to an array type, the result is the alignment of the
element type[.](#expr.alignof-3.sentence-2)
#### [7.6.2.7](#expr.unary.noexcept) noexcept operator [[expr.unary.noexcept]](expr.unary.noexcept)
[noexcept-expression:](#nt:noexcept-expression "7.6.2.7noexcept operator[expr.unary.noexcept]")
noexcept ( [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") )
[1](#expr.unary.noexcept-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5733)
The operand of the noexcept operator
is an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3Context dependence"))[.](#expr.unary.noexcept-1.sentence-1)
If the operand is a prvalue,
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) is applied[.](#expr.unary.noexcept-1.sentence-2)
[2](#expr.unary.noexcept-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5739)
The result of the noexcept operator is a prvalue of type bool[.](#expr.unary.noexcept-2.sentence-1)
The result is false if
the full-expression of the operand is potentially-throwing ([[except.spec]](except.spec "14.5Exception specifications")), andtrue otherwise[.](#expr.unary.noexcept-2.sentence-2)
[*Note [1](#expr.unary.noexcept-note-1)*:
A [*noexcept-expression*](#nt:noexcept-expression "7.6.2.7noexcept operator[expr.unary.noexcept]") is an integral constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#expr.unary.noexcept-2.sentence-3)
— *end note*]
#### [7.6.2.8](#expr.new) New [[expr.new]](expr.new)
[1](#expr.new-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5752)
The [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") attempts to create an object of the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") ([[dcl.name]](dcl.name "9.3.2Type names")) to which
it is applied[.](#expr.new-1.sentence-1)
The type of that object is the [*allocated type*](#def:type,allocated "7.6.2.8New[expr.new]")[.](#expr.new-1.sentence-2)
This type shall be a complete object type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General")),
but not an abstract class type ([[class.abstract]](class.abstract "11.7.4Abstract classes")) or array
thereof ([[intro.object]](intro.object "6.8.2Object model"))[.](#expr.new-1.sentence-3)
[*Note [1](#expr.new-note-1)*:
Because references are not objects, references cannot be created by[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")*s*[.](#expr.new-1.sentence-4)
— *end note*]
[*Note [2](#expr.new-note-2)*:
The [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") can be a cv-qualified type, in which case the
object created by the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") has a cv-qualified type[.](#expr.new-1.sentence-5)
— *end note*]
[new-expression:](#nt:new-expression "7.6.2.8New[expr.new]")
::opt new [*new-placement*](#nt:new-placement "7.6.2.8New[expr.new]")opt [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]")opt
::opt new [*new-placement*](#nt:new-placement "7.6.2.8New[expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]")opt
[new-placement:](#nt:new-placement "7.6.2.8New[expr.new]")
( [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") )
[new-type-id:](#nt:new-type-id "7.6.2.8New[expr.new]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8New[expr.new]")opt
[new-declarator:](#nt:new-declarator "7.6.2.8New[expr.new]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8New[expr.new]")opt
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]")
[noptr-new-declarator:](#nt:noptr-new-declarator "7.6.2.8New[expr.new]")
[ [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[new-initializer:](#nt:new-initializer "7.6.2.8New[expr.new]")
( [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[2](#expr.new-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5813)
If a [placeholder type](dcl.spec.auto "9.2.9.7Placeholder type specifiers[dcl.spec.auto]") or
a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))
appears in the[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") of a [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") or[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]"),
the allocated type is deduced as follows:
Let*init* be the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]"), if any,
andT be the [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of
the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]"), then the allocated type is the type
deduced for the variable x in the invented
declaration ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")):T x *init* ;
[*Example [1](#expr.new-example-1)*: new auto(1); // allocated type is intauto x = new auto('a'); // allocated type is char, x is of type char*template<class T> struct A { A(T, T); };auto y = new A{1, 2}; // allocated type is A<int> — *end example*]
[3](#expr.new-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5841)
The [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") in a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") is the longest
possible sequence of [*new-declarator*](#nt:new-declarator "7.6.2.8New[expr.new]")*s*[.](#expr.new-3.sentence-1)
[*Note [3](#expr.new-note-3)*:
This prevents ambiguities between the declarator operators &, &&,*, and [] and their expression counterparts[.](#expr.new-3.sentence-2)
— *end note*]
[*Example [2](#expr.new-example-2)*: new int * i; // syntax error: parsed as (new int*) i, not as (new int)*i
The * is the pointer declarator and not the multiplication
operator[.](#expr.new-3.sentence-3)
— *end example*]
[4](#expr.new-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5856)
[*Note [4](#expr.new-note-4)*:
Parentheses in a [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") of a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") can have surprising effects[.](#expr.new-4.sentence-1)
[*Example [3](#expr.new-example-3)*:
new int(*[10])(); // error is ill-formed because the binding is(new int) (*[10])(); // error
Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound
types ([[basic.compound]](basic.compound "6.9.4Compound types")):
new (int (*[10])()); allocates an array of 10 pointers to functions (taking no
argument and returning int)[.](#expr.new-4.sentence-4)
— *end example*]
— *end note*]
[5](#expr.new-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5882)
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]") appertains
to the associated array type[.](#expr.new-5.sentence-1)
[6](#expr.new-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5886)
Every [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") in a[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]") shall be a converted constant
expression ([[expr.const]](expr.const "7.7Constant expressions")) of type std::size_t and
its value shall be greater than zero[.](#expr.new-6.sentence-1)
[*Example [4](#expr.new-example-4)*:
Given the definition int n = 42,new float[n][5] is well-formed (because n is the[*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]")), butnew float[5][n] is ill-formed (because n is not a
constant expression)[.](#expr.new-6.sentence-2)
Furthermore,new float[0] is well-formed
(because 0 is the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]"),
where a value of zero results in the allocation of an array with no elements),
but new float[n][0] is ill-formed
(because 0 is the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]"),
where only values greater than zero are allowed)[.](#expr.new-6.sentence-3)
— *end example*]
[7](#expr.new-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5908)
If the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") denotes an array type of unknown bound ([[dcl.array]](dcl.array "9.3.4.5Arrays")),
the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") shall not be omitted;
the allocated object is an array with n elements,
where n is determined from the number of initial elements
supplied in
the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"), [[dcl.init.string]](dcl.init.string "9.5.3Character arrays"))[.](#expr.new-7.sentence-1)
[8](#expr.new-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5917)
If the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]") is present, it is implicitly converted to std::size_t[.](#expr.new-8.sentence-1)
The value of the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") is invalid if
- [(8.1)](#expr.new-8.1)
the expression is of non-class type and its value before converting tostd::size_t is less than zero;
- [(8.2)](#expr.new-8.2)
the expression is of class type and its value before application of the second
standard conversion ([[over.ics.user]](over.ics.user "12.2.4.2.3User-defined conversion sequences"))[59](#footnote-59 "If the conversion function returns a signed integer type, the second standard conversion converts to the unsigned type std::size_­t and thus thwarts any attempt to detect a negative value afterwards.") is less than zero;
- [(8.3)](#expr.new-8.3)
its value is such that the size of the allocated object would exceed theimplementation-defined [limit](implimits "Annex B(informative)Implementation quantities[implimits]"); or
- [(8.4)](#expr.new-8.4)
the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") and the
number of array elements for which initializers are provided (including the
terminating '\0' in a [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") ([[lex.string]](lex.string "5.13.5String literals"))) exceeds the
number of elements to initialize[.](#expr.new-8.sentence-2)
If the value of the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") is invalid after converting to std::size_t:
- [(8.5)](#expr.new-8.5)
if the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") is a potentially-evaluated core constant expression,
the program is ill-formed;
- [(8.6)](#expr.new-8.6)
otherwise, an allocation function is not called; instead
* [(8.6.1)](#expr.new-8.6.1)
if the allocation function that would have been called
has a non-throwing exception specification ([[except.spec]](except.spec "14.5Exception specifications")),
the value of the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") is the null pointer value of the required result type;
* [(8.6.2)](#expr.new-8.6.2)
otherwise, the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") terminates by throwing an
exception of a type that would match a handler ([[except.handle]](except.handle "14.4Handling an exception")) of type[std::bad_array_new_length](new.badlength "17.6.4.2Class bad_­array_­new_­length[new.badlength]")[.](#expr.new-8.sentence-3)
When the value of the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") is zero, the allocation
function is called to allocate an array with no elements[.](#expr.new-8.sentence-4)
[9](#expr.new-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5972)
If the allocated type is an array,
the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"), and
the [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") is potentially-evaluated and not a core constant expression,
the semantic constraints of copy-initializing a hypothetical element of
the array from an empty initializer list
are checked ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization"))[.](#expr.new-9.sentence-1)
[*Note [5](#expr.new-note-5)*:
The array can contain more elements than there are
elements in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
requiring initialization of the remainder of the array elements from
an empty initializer list[.](#expr.new-9.sentence-2)
— *end note*]
[10](#expr.new-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5987)
Objects created by a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") have dynamic storage
duration ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5Dynamic storage duration"))[.](#expr.new-10.sentence-1)
[*Note [6](#expr.new-note-6)*:
The lifetime of such an object is not necessarily restricted to the
scope in which it is created[.](#expr.new-10.sentence-2)
— *end note*]
[11](#expr.new-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5997)
When the allocated type is “array of N T”
(that is, the [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8New[expr.new]") syntax is used or the[*new-type-id*](#nt:new-type-id "7.6.2.8New[expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") denotes an array type),
the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") yields a prvalue of type “pointer to T”
that points to the initial element (if any) of the array[.](#expr.new-11.sentence-1)
Otherwise, let T be the allocated type;
the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") is a prvalue of type “pointer to T”
that points to the object created[.](#expr.new-11.sentence-2)
[*Note [7](#expr.new-note-7)*:
Both new int and new int[10] have type int* and
the type of new int[i][10] is int (*)[10][.](#expr.new-11.sentence-3)
— *end note*]
[12](#expr.new-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6013)
A [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") may obtain storage for the object by calling an
allocation function ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions"))[.](#expr.new-12.sentence-1)
If
the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") terminates by throwing an exception, it
may release storage by calling a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions[basic.stc.dynamic.deallocation]")[.](#expr.new-12.sentence-2)
If the allocated type
is a non-array type, the allocation function's name isoperator new and the deallocation function's name isoperator delete[.](#expr.new-12.sentence-3)
If the allocated type is an array type, the
allocation function's name isoperator new[] and the deallocation function's name isoperator delete[][.](#expr.new-12.sentence-4)
[*Note [8](#expr.new-note-8)*:
An implementation is expected to provide default definitions for the global
allocation
functions ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5Dynamic storage duration"), [[new.delete.single]](new.delete.single "17.6.3.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array forms"))[.](#expr.new-12.sentence-5)
A C++ program can provide alternative definitions of
these functions ([[replacement.functions]](replacement.functions "16.4.5.6Replacement functions")) and/or class-specific
versions ([[class.free]](class.free "11.4.11Allocation and deallocation functions"))[.](#expr.new-12.sentence-6)
The set of allocation and deallocation functions that can be called
by a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") can include functions that do not perform allocation or deallocation;
for example, see [[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms")[.](#expr.new-12.sentence-7)
— *end note*]
[13](#expr.new-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6043)
If the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") does not begin with a unary :: operator and
the allocated type is a class type T or array thereof,
a search is performed for the allocation function's name in the scope
of T ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#expr.new-13.sentence-1)
Otherwise, or if nothing is found,
the allocation function's name is looked up by
searching for it in the global scope[.](#expr.new-13.sentence-2)
[14](#expr.new-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6054)
An implementation is allowed to omit a call to a replaceable global allocation
function ([[new.delete.single]](new.delete.single "17.6.3.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array forms"))[.](#expr.new-14.sentence-1)
When it does so,
the storage is instead provided by the implementation or provided by extending
the allocation of another [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.new-14.sentence-2)
[15](#expr.new-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6060)
During an evaluation of a constant expression,
a call to a replaceable allocation function is always omitted ([[expr.const]](expr.const "7.7Constant expressions"))[.](#expr.new-15.sentence-1)
[16](#expr.new-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6064)
The implementation may
extend the allocation of a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") e1 to provide
storage for a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") e2 if the
following would be true were the allocation not extended:
- [(16.1)](#expr.new-16.1)
the evaluation of e1 is sequenced before the evaluation ofe2, and
- [(16.2)](#expr.new-16.2)
e2 is evaluated whenever e1 obtains storage, and
- [(16.3)](#expr.new-16.3)
both e1 and e2 invoke the same replaceable global
allocation function, and
- [(16.4)](#expr.new-16.4)
if the allocation function invoked by e1 and e2 is
throwing, any exceptions thrown in the evaluation of either e1 ore2 would be first caught in the same handler, and
- [(16.5)](#expr.new-16.5)
the pointer values produced by e1 and e2 are operands to
evaluated [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]")*s*, and
- [(16.6)](#expr.new-16.6)
the evaluation of e2 is sequenced before the evaluation of the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") whose operand is the pointer value produced
by e1[.](#expr.new-16.sentence-1)
[*Example [5](#expr.new-example-5)*: 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 example*]
[17](#expr.new-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6114)
When a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") calls an allocation function and that
allocation has not been extended, the[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") passes the amount of space requested to the
allocation function as the first argument of typestd::size_t[.](#expr.new-17.sentence-1)
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 ([[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms"))[.](#expr.new-17.sentence-2)
For arrays ofchar, unsigned char, and std::byte,
the difference between the
result of the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") and the address returned by the
allocation function shall be an integral multiple of the
strictest fundamental[alignment requirement](basic.align "6.8.3Alignment[basic.align]") of any object type whose size
is no greater than the size of the array being created[.](#expr.new-17.sentence-3)
[*Note [9](#expr.new-note-9)*:
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[.](#expr.new-17.sentence-4)
— *end note*]
[18](#expr.new-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6140)
When a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") 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[.](#expr.new-18.sentence-1)
[19](#expr.new-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6147)
The [*new-placement*](#nt:new-placement "7.6.2.8New[expr.new]") syntax is used to supply additional
arguments to an allocation function; such an expression is called
a [*placement* ](#def:new-expression,placement "7.6.2.8New[expr.new]")*[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")*[.](#expr.new-19.sentence-1)
[20](#expr.new-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6153)
Overload resolution is
performed on a function call created by assembling an argument list[.](#expr.new-20.sentence-1)
The first argument is
the amount of space requested,
and has type std::size_t[.](#expr.new-20.sentence-2)
If the type of the allocated object has new-extended alignment,
the next argument is
the type's alignment,
and has type std::align_val_t[.](#expr.new-20.sentence-3)
If the [*new-placement*](#nt:new-placement "7.6.2.8New[expr.new]") syntax is used,
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* in its [*expression-list*](#nt:expression-list "7.6.1.1General[expr.post.general]") are the succeeding arguments[.](#expr.new-20.sentence-4)
If no matching function is found then
- [(20.1)](#expr.new-20.1)
if the allocated object type has new-extended alignment,
the alignment argument is removed from the argument list;
- [(20.2)](#expr.new-20.2)
otherwise, an argument that
is the type's alignment and has type std::align_val_t is added into the argument list immediately after the first argument;
and then overload resolution is performed again[.](#expr.new-20.sentence-5)
[21](#expr.new-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6181)
[*Example [6](#expr.new-example-6)*:
- [(21.1)](#expr.new-21.1)
new T results in one of the following calls:operator new(sizeof(T))operator new(sizeof(T), std::align_val_t(alignof(T)))
- [(21.2)](#expr.new-21.2)
new(2,f) T results in one of the following calls:operator new(sizeof(T), 2, f)operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)
- [(21.3)](#expr.new-21.3)
new T[5] results in one of the following calls:operator new[](sizeof(T) * 5 + x)operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)))
- [(21.4)](#expr.new-21.4)
new(2,f) T[5] results in one of the following calls:operator new[](sizeof(T) * 5 + x, 2, f)operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)), 2, f)
Here, each instance of x is a non-negative unspecified value
representing array allocation overhead; the result of the[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") will be offset by this amount from the value
returned by operator new[].
This overhead may be applied in all
array [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")*s*, including those referencing
a placement allocation function, except when referencing
the library function operator new[](std::size_t, void*)[.](#expr.new-21.sentence-1)
The amount of overhead may vary from one
invocation of new to another[.](#expr.new-21.sentence-2)
— *end example*]
[22](#expr.new-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6216)
[*Note [10](#expr.new-note-10)*:
Unless an allocation function has a non-throwing[exception specification](except.spec "14.5Exception specifications[except.spec]"),
it indicates failure to allocate storage by throwing astd::bad_alloc exception ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions"), [[except]](except "14Exception handling"), [[bad.alloc]](bad.alloc "17.6.4.1Class bad_­alloc"));
it returns a non-null pointer otherwise[.](#expr.new-22.sentence-1)
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[.](#expr.new-22.sentence-2)
— *end note*]
If the allocation function is a non-allocating
form ([[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms")) that returns null,
the behavior is undefined[.](#expr.new-22.sentence-3)
Otherwise,
if the allocation function returns null, initialization shall not be
done, the deallocation function shall not be called, and the value of
the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") shall be null[.](#expr.new-22.sentence-4)
[23](#expr.new-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6238)
[*Note [11](#expr.new-note-11)*:
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[.](#expr.new-23.sentence-1)
The block of storage is assumed to be
appropriately aligned ([[basic.align]](basic.align "6.8.3Alignment"))
and of the requested size[.](#expr.new-23.sentence-2)
The address of the created object will not
necessarily be the same as that of the block if the object is an array[.](#expr.new-23.sentence-3)
— *end note*]
[24](#expr.new-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6248)
A [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") that creates an object of type T initializes that object as follows:
- [(24.1)](#expr.new-24.1)
If the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") is omitted, the object is
default-initialized ([[dcl.init]](dcl.init "9.5Initializers"))[.](#expr.new-24.1.sentence-1)
[*Note [12](#expr.new-note-12)*:
If no initialization
is performed, the object has an indeterminate value[.](#expr.new-24.1.sentence-2)
— *end note*]
- [(24.2)](#expr.new-24.2)
Otherwise, the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") is interpreted according to
the initialization rules of [[dcl.init]](dcl.init "9.5Initializers") for direct-initialization[.](#expr.new-24.2.sentence-1)
[25](#expr.new-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6267)
The invocation of the allocation function is sequenced before
the evaluations of expressions in the [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]")[.](#expr.new-25.sentence-1)
Initialization of
the allocated object is sequenced before thevalue computation of the[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.new-25.sentence-2)
[26](#expr.new-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6277)
If the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") creates an array of objects of class type, the destructor is potentially
invoked ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#expr.new-26.sentence-1)
[27](#expr.new-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6282)
If any part of the object initialization described above[60](#footnote-60 "This can include evaluating a new-initializer and/or calling a constructor.") 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 [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.new-27.sentence-1)
If no unambiguous matching deallocation function can be found,
propagating the exception does not cause the object's memory to be
freed[.](#expr.new-27.sentence-2)
[*Note [13](#expr.new-note-13)*:
This is appropriate when the called allocation function does not
allocate memory; otherwise, it is likely to result in a memory leak[.](#expr.new-27.sentence-3)
— *end note*]
[28](#expr.new-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6302)
If the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") does not begin with
a unary :: operator and
the allocated type is a class type T or an array thereof,
a search is performed for the deallocation function's name
in the scope of T[.](#expr.new-28.sentence-1)
Otherwise, or if nothing is found,
the deallocation function's name is looked up by
searching for it in the global scope[.](#expr.new-28.sentence-2)
[29](#expr.new-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6312)
A declaration of a placement deallocation function matches the
declaration of a placement allocation function if it has the same number
of parameters and, after parameter transformations ([[dcl.fct]](dcl.fct "9.3.4.6Functions")), all
parameter types except the first are identical[.](#expr.new-29.sentence-1)
If
the lookup finds a single matching deallocation function, that function
will be called; otherwise, no deallocation function will be called[.](#expr.new-29.sentence-2)
If
the lookup finds a usual deallocation
function
and that function,
considered as a placement deallocation function, would have been
selected as a match for the allocation function, the program is
ill-formed[.](#expr.new-29.sentence-3)
For a non-placement allocation function, the normal deallocation
function lookup is used to find the matching deallocation
function ([[expr.delete]](#expr.delete "7.6.2.9Delete"))[.](#expr.new-29.sentence-4)
In any case,
the matching deallocation function (if any) shall be non-deleted and
accessible from the point where the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") appears[.](#expr.new-29.sentence-5)
[*Example [7](#expr.new-example-7)*: 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 example*]
[30](#expr.new-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6345)
If a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") calls a deallocation function, it passes
the value returned from the allocation function call as the first
argument of type void*[.](#expr.new-30.sentence-1)
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 [*new-placement*](#nt:new-placement "7.6.2.8New[expr.new]") syntax[.](#expr.new-30.sentence-2)
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[.](#expr.new-30.sentence-3)
[59)](#footnote-59)[59)](#footnoteref-59)
If the conversion function
returns a signed integer type, the second standard conversion converts to the
unsigned type std::size_t and thus thwarts any attempt to detect a
negative value afterwards[.](#footnote-59.sentence-1)
[60)](#footnote-60)[60)](#footnoteref-60)
This can
include evaluating a [*new-initializer*](#nt:new-initializer "7.6.2.8New[expr.new]") and/or calling
a constructor[.](#footnote-60.sentence-1)
#### [7.6.2.9](#expr.delete) Delete [[expr.delete]](expr.delete)
[1](#expr.delete-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6360)
The [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") operator destroys a[most derived object](intro.object#def:most_derived_object "6.8.2Object model[intro.object]") or array created by a[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.delete-1.sentence-1)
[delete-expression:](#nt:delete-expression "7.6.2.9Delete[expr.delete]")
::opt delete [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
::opt delete [ ] [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
The first alternative is a[*single-object delete expression*](#def:delete,single-object "7.6.2.9Delete[expr.delete]"), and the
second is an [*array delete expression*](#def:delete,array "7.6.2.9Delete[expr.delete]")[.](#expr.delete-1.sentence-2)
Whenever the delete keyword is immediately followed by empty square
brackets, it shall be interpreted as the second alternative[.](#expr.delete-1.sentence-3)[61](#footnote-61 "A lambda-expression with a lambda-introducer that consists of empty square brackets can follow the delete keyword if the lambda-expression is enclosed in parentheses.")
If the operand is of
class type, it is contextually implicitly converted ([[conv]](conv "7.3Standard conversions"))
to a pointer to object
type
and the converted operand is used in place of the original operand
for the remainder of this subclause[.](#expr.delete-1.sentence-4)
Otherwise, it shall be a prvalue of pointer to object type[.](#expr.delete-1.sentence-5)
The [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") has typevoid[.](#expr.delete-1.sentence-6)
[2](#expr.delete-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6394)
In a single-object delete expression, the value of the operand ofdelete may be a null pointer value,
a pointer value
that resulted from a previous non-array [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]"), or
a pointer to a base class subobject
of an object created by such a [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.delete-2.sentence-1)
If not, the behavior is undefined[.](#expr.delete-2.sentence-2)
In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from
a previous array [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") whose
allocation function was not a non-allocating form ([[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms"))[.](#expr.delete-2.sentence-3)[62](#footnote-62 "For nonzero-length arrays, this is the same as a pointer to the first element of the array created by that new-expression. Zero-length arrays do not have a first element.")
If not, the behavior is undefined[.](#expr.delete-2.sentence-4)
[*Note [1](#expr.delete-note-1)*:
This means that the syntax of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") must
match the type of the object allocated by new, not the syntax of the[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#expr.delete-2.sentence-5)
— *end note*]
[*Note [2](#expr.delete-note-2)*:
A pointer to a const type can be the operand of a[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]"); it is not necessary to cast away the
constness ([[expr.const.cast]](#expr.const.cast "7.6.1.11Const cast")) of the pointer expression before it is
used as the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]")[.](#expr.delete-2.sentence-6)
— *end note*]
[3](#expr.delete-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6427)
In a single-object delete expression, if the static type of the object to be
deleted is not similar ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) 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[.](#expr.delete-3.sentence-1)
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[.](#expr.delete-3.sentence-2)
[4](#expr.delete-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6439)
If the object being deleted has incomplete class type at the point of deletion,
the program is ill-formed[.](#expr.delete-4.sentence-1)
[5](#expr.delete-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6444)
If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") is not a
null pointer value
and the selected deallocation function (see below)
is not a destroying operator delete,
evaluating the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") invokes the
destructor (if any) for the object or the elements of the array being
deleted[.](#expr.delete-5.sentence-1)
The destructor shall be accessible from the point where
the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") appears[.](#expr.delete-5.sentence-2)
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 [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#expr.delete-5.sentence-3)
[6](#expr.delete-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6459)
If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") is not a
null pointer value, then:
- [(6.1)](#expr.delete-6.1)
If the allocation call for the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") for the object to
be deleted was not omitted and the allocation was not extended ([[expr.new]](#expr.new "7.6.2.8New")), the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") shall call a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions[basic.stc.dynamic.deallocation]")[.](#expr.delete-6.1.sentence-1)
The value returned from the
allocation call of the [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") shall be passed as the
first argument to the deallocation function[.](#expr.delete-6.1.sentence-2)
- [(6.2)](#expr.delete-6.2)
Otherwise, if the allocation was extended or was provided by extending the
allocation of another [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]"), and the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") for every other pointer value produced by a[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") that had storage provided by the extended[*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") has been evaluated, the[*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") shall call a deallocation function[.](#expr.delete-6.2.sentence-1)
The value
returned from the allocation call of the extended [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]") shall be passed as the first argument to the deallocation function[.](#expr.delete-6.2.sentence-2)
- [(6.3)](#expr.delete-6.3)
Otherwise, the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") will not call a
deallocation function[.](#expr.delete-6.3.sentence-1)
[*Note [3](#expr.delete-note-3)*:
The deallocation function is called regardless of whether the destructor
for the object or some element of the array throws an exception[.](#expr.delete-6.sentence-2)
— *end note*]
If the value of the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") is a
null pointer value, it is unspecified whether a deallocation function will be
called as described above[.](#expr.delete-6.sentence-3)
[7](#expr.delete-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6493)
If a deallocation function is called,
it is operator delete for a single-object delete expression oroperator delete[] for an array delete expression[.](#expr.delete-7.sentence-1)
[*Note [4](#expr.delete-note-4)*:
An implementation provides default definitions of the global
deallocation functions ([[new.delete.single]](new.delete.single "17.6.3.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array forms"))[.](#expr.delete-7.sentence-2)
A C++ program can provide alternative definitions of these
functions ([[replacement.functions]](replacement.functions "16.4.5.6Replacement functions")), and/or class-specific
versions ([[class.free]](class.free "11.4.11Allocation and deallocation functions"))[.](#expr.delete-7.sentence-3)
— *end note*]
[8](#expr.delete-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6506)
If the keyword delete in a [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") is not preceded by the unary :: operator and the type of the operand is
a pointer to a (possibly cv-qualified) class type T or (possibly multidimensional) array thereof:
- [(8.1)](#expr.delete-8.1)
For a single-object delete expression,
if the operand is a pointer to cv T andT has a virtual destructor,
the deallocation function is the one selected at the point of definition of
the dynamic type's virtual destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#expr.delete-8.1.sentence-1)
- [(8.2)](#expr.delete-8.2)
Otherwise,
a search is performed for the deallocation function's name
in the scope of T[.](#expr.delete-8.2.sentence-1)
Otherwise, or if nothing is found,
the deallocation function's name is looked up by
searching for it in the global scope[.](#expr.delete-8.sentence-2)
In any case, any declarations
other than of usual deallocation functions ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"))
are discarded[.](#expr.delete-8.sentence-3)
[*Note [5](#expr.delete-note-5)*:
If only a placement deallocation function is found in a class,
the program is ill-formed because the lookup set is empty ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#expr.delete-8.sentence-4)
— *end note*]
[9](#expr.delete-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6534)
The deallocation function to be called is selected as follows:
- [(9.1)](#expr.delete-9.1)
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[.](#expr.delete-9.1.sentence-1)
- [(9.2)](#expr.delete-9.2)
If the type has new-extended alignment,
a function with a parameter of type std::align_val_t is preferred;
otherwise a function without such a parameter is preferred[.](#expr.delete-9.2.sentence-1)
If any preferred functions are found,
all non-preferred functions are eliminated from further consideration[.](#expr.delete-9.2.sentence-2)
- [(9.3)](#expr.delete-9.3)
If exactly one function remains,
that function is selected and the selection process terminates[.](#expr.delete-9.3.sentence-1)
- [(9.4)](#expr.delete-9.4)
If the deallocation functions belong to a class scope,
the one without a parameter of type std::size_t is selected[.](#expr.delete-9.4.sentence-1)
- [(9.5)](#expr.delete-9.5)
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 std::size_t is selected[.](#expr.delete-9.5.sentence-1)
- [(9.6)](#expr.delete-9.6)
Otherwise, it is unspecified
whether a deallocation function with a parameter of type std::size_t is selected[.](#expr.delete-9.6.sentence-1)
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 [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") appears[.](#expr.delete-9.sentence-2)
[10](#expr.delete-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6569)
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[.](#expr.delete-10.sentence-1)
[*Note [6](#expr.delete-note-6)*:
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[.](#expr.delete-10.sentence-2)
— *end note*]
For an array delete expression,
the deleted object is
the array object[.](#expr.delete-10.sentence-3)
When a [*delete-expression*](#nt:delete-expression "7.6.2.9Delete[expr.delete]") 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 ([[expr.new]](#expr.new "7.6.2.8New")) in an array delete expression,
as its first argument[.](#expr.delete-10.sentence-4)
[*Note [7](#expr.delete-note-7)*:
Any cv-qualifiers in the type of the deleted object
are ignored when forming this argument[.](#expr.delete-10.sentence-5)
— *end note*]
If a destroying operator delete is used,
an unspecified value
is passed as the argument
corresponding to the parameter of type std::destroying_delete_t[.](#expr.delete-10.sentence-6)
If a deallocation function
with a parameter of type std::align_val_t is used,
the alignment of the type of the deleted object
is passed as the corresponding argument[.](#expr.delete-10.sentence-7)
If a deallocation function
with a parameter of type 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[.](#expr.delete-10.sentence-8)
[*Note [8](#expr.delete-note-8)*:
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 ([[new.delete.single]](new.delete.single "17.6.3.2Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3Array forms"))[.](#expr.delete-10.sentence-9)
— *end note*]
[61)](#footnote-61)[61)](#footnoteref-61)
A[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") with a [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1General[expr.prim.lambda.general]") that consists of empty square brackets can follow the delete keyword
if the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is enclosed in parentheses[.](#footnote-61.sentence-1)
[62)](#footnote-62)[62)](#footnoteref-62)
For nonzero-length
arrays, this is the same as a pointer to the first
element of the array created by that [*new-expression*](#nt:new-expression "7.6.2.8New[expr.new]")[.](#footnote-62.sentence-1)
Zero-length arrays do not have a first element[.](#footnote-62.sentence-2)
#### [7.6.2.10](#expr.reflect) The reflection operator [[expr.reflect]](expr.reflect)
[reflect-expression:](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")
^^ ::
^^ [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
^^ [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
^^ [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[reflection-name:](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[1](#expr.reflect-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6637)
The unary ^^ operator,
called the [*reflection operator*](#def:operator,reflection "7.6.2.10The reflection operator[expr.reflect]"),
yields a prvalue of type std::meta::info ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#expr.reflect-1.sentence-1)
[*Note [1](#expr.reflect-note-1)*:
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 [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")*s*[.](#expr.reflect-1.sentence-2)
— *end note*]
[2](#expr.reflect-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6648)
The component names of a [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") are those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") (if any) and
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")[.](#expr.reflect-2.sentence-1)
The terminal name of a [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") shall denote a template[.](#expr.reflect-2.sentence-2)
[3](#expr.reflect-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6656)
A [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") is parsed as
the longest possible sequence of tokens
that could syntactically form a [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")[.](#expr.reflect-3.sentence-1)
An unparenthesized [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") that represents a template shall not be followed by <[.](#expr.reflect-3.sentence-2)
[*Example [1](#expr.reflect-example-1)*: static_assert(std::meta::is_type(^^int())); // ^^ applies to the type-id 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: ^^ applies to the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") int&& r == ^^int & true; // error: ^^ applies to the type-id int& r == (^^int) && true; // OK r == ^^int &&&& true; // error: int &&&& is not a valid [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")^^X < xv; // error: [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") that represents a template is followed by <(^^X) < xv; // OK^^X<true> < xv; // OK} — *end example*]
[4](#expr.reflect-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6680)
A [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") of the form ^^:: represents the global namespace[.](#expr.reflect-4.sentence-1)
[5](#expr.reflect-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6684)
If a [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") R matches
the form ^^[*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]"),
it is interpreted as such;
the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is looked up and
the representation of R is determined as follows:
- [(5.1)](#expr.reflect-5.1)
If lookup finds a declaration
that replaced a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") during a single search ([[basic.lookup.general]](basic.lookup.general "6.5.1General"), [[namespace.udecl]](namespace.udecl "9.10The using declaration")),R is ill-formed[.](#expr.reflect-5.1.sentence-1)
[*Example [2](#expr.reflect-example-2)*: struct A { struct S {}; };struct B : A { using A::S; };constexpr std::meta::info r1 = ^^B::S; // error: A::S found through [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]")struct C : virtual B { struct S {}; };struct D : virtual B, C {};
D::S s; // OK, names C::S per [[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")constexpr std::meta::info r2 = ^^D::S; // OK, result C::S not found through [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") — *end example*]
- [(5.2)](#expr.reflect-5.2)
Otherwise, if lookup finds a namespace alias ([[namespace.alias]](namespace.alias "9.9.3Namespace alias")),R represents that namespace alias[.](#expr.reflect-5.2.sentence-1)
For any other [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]"),R represents the denoted namespace[.](#expr.reflect-5.2.sentence-2)
- [(5.3)](#expr.reflect-5.3)
Otherwise, if lookup finds a namespace ([[basic.namespace]](basic.namespace "9.9Namespaces")),R represents that namespace[.](#expr.reflect-5.3.sentence-1)
- [(5.4)](#expr.reflect-5.4)
Otherwise, if lookup finds a concept ([[temp.concept]](temp.concept "13.7.9Concept definitions")),R represents the denoted concept[.](#expr.reflect-5.4.sentence-1)
- [(5.5)](#expr.reflect-5.5)
Otherwise, if lookup finds a template ([[temp.names]](temp.names "13.3Names of template specializations")),
the representation of R is determined as follows:
* [(5.5.1)](#expr.reflect-5.5.1)
If lookup finds an injected-class-name ([[class.pre]](class.pre "11.1Preamble")), then:
+
[(5.5.1.1)](#expr.reflect-5.5.1.1)
If the [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") is of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"),
then R represents the class template named by the injected-class-name[.](#expr.reflect-5.5.1.1.sentence-1)
+
[(5.5.1.2)](#expr.reflect-5.5.1.2)
Otherwise, the injected-class-name shall be unambiguous
when considered as a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") andR represents the class template specialization so named[.](#expr.reflect-5.5.1.2.sentence-1)
* [(5.5.2)](#expr.reflect-5.5.2)
Otherwise, if lookup finds an overload set,
that overload set shall contain only
declarations of a unique function template F;R represents F[.](#expr.reflect-5.5.2.sentence-1)
* [(5.5.3)](#expr.reflect-5.5.3)
Otherwise, if lookup finds
a class template, variable template, or alias template,R represents that template[.](#expr.reflect-5.5.3.sentence-1)
[*Note [2](#expr.reflect-note-2)*:
Lookup never finds a partial or explicit specialization[.](#expr.reflect-5.5.3.sentence-2)
— *end note*]
- [(5.6)](#expr.reflect-5.6)
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[.](#expr.reflect-5.6.sentence-1)
- [(5.7)](#expr.reflect-5.7)
Otherwise, if lookup finds a class or an enumeration,R represents the denoted type[.](#expr.reflect-5.7.sentence-1)
- [(5.8)](#expr.reflect-5.8)
Otherwise, if lookup finds a class member of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")), R represents that class member[.](#expr.reflect-5.8.sentence-1)
- [(5.9)](#expr.reflect-5.9)
Otherwise,
the [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") shall be an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") I and R is ^^I (see below)[.](#expr.reflect-5.9.sentence-1)
[6](#expr.reflect-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6764)
A [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") R of the form^^[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") represents an entity determined as follows:
- [(6.1)](#expr.reflect-6.1)
If the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") designates
a placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1General")),R is ill-formed[.](#expr.reflect-6.1.sentence-1)
- [(6.2)](#expr.reflect-6.2)
Otherwise, if the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") names a type alias
that is a specialization of an alias template ([[temp.alias]](temp.alias "13.7.8Alias templates")),R represents that type alias[.](#expr.reflect-6.2.sentence-1)
- [(6.3)](#expr.reflect-6.3)
Otherwise, R represents the type denoted by the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#expr.reflect-6.3.sentence-1)
[7](#expr.reflect-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6781)
A [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") R of the form^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") represents an entity determined as follows:
- [(7.1)](#expr.reflect-7.1)
If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denotes
* [(7.1.1)](#expr.reflect-7.1.1)
a variable declared by
an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures")),
* [(7.1.2)](#expr.reflect-7.1.2)
a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")),
* [(7.1.3)](#expr.reflect-7.1.3)
a local parameter introduced by
a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") ([[expr.prim.req]](expr.prim.req "7.5.8Requires expressions")), or
* [(7.1.4)](#expr.reflect-7.1.4)
a local entity E ([[basic.pre]](basic.pre "6.1Preamble")) for which a lambda scope intervenes
between the point at which E was introduced and R,
then R is ill-formed[.](#expr.reflect-7.1.sentence-1)
- [(7.2)](#expr.reflect-7.2)
Otherwise, if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denotes an overload set S,
overload resolution for the expression &S with no target
shall select a unique function ([[over.over]](over.over "12.3Address of an overload set"));R represents that function[.](#expr.reflect-7.2.sentence-1)
- [(7.3)](#expr.reflect-7.3)
Otherwise, if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denotes
a variable, structured binding, enumerator, or non-static data member,R represents that entity[.](#expr.reflect-7.3.sentence-1)
- [(7.4)](#expr.reflect-7.4)
Otherwise, R is ill-formed[.](#expr.reflect-7.4.sentence-1)
[*Note [3](#expr.reflect-note-3)*:
This includes [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")*s* that name a constant template parameter and[*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]")*s*[.](#expr.reflect-7.4.sentence-2)
— *end note*]
The [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") of
a [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3Context dependence"))[.](#expr.reflect-7.sentence-2)
[*Example [3](#expr.reflect-example-3)*: 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>; // OKconstexpr std::meta::info b = ^^fn<int>; // error: ambiguousconstexpr std::meta::info c = ^^std::vector; // OKtemplate<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 Yconstexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type ([[basic.lookup.general]](basic.lookup.general "6.5.1General")) — *end example*]
### [7.6.3](#expr.cast) Explicit type conversion (cast notation) [[expr.cast]](expr.cast)
[1](#expr.cast-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6850)
The result of the expression (T) [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") is
of type T[.](#expr.cast-1.sentence-1)
The result is an lvalue if T is an lvalue
reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue[.](#expr.cast-1.sentence-2)
[*Note [1](#expr.cast-note-1)*:
If T is a non-class type that is cv-qualified, the[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* are discarded when determining the type of the
resulting prvalue; see [[expr.prop]](expr.prop "7.2Properties of expressions")[.](#expr.cast-1.sentence-3)
— *end note*]
[2](#expr.cast-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6861)
An explicit type conversion can be expressed using functional
notation ([[expr.type.conv]](#expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")), a type conversion operator
(dynamic_cast, static_cast, reinterpret_cast,const_cast), or the [*cast*](#def:cast) notation[.](#expr.cast-2.sentence-1)
[cast-expression:](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[*unary-expression*](#nt:unary-expression "7.6.2.1General[expr.unary.general]")
( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[3](#expr.cast-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6873)
Any type conversion not mentioned below and not explicitly defined by
the user ([[class.conv]](class.conv "11.4.8Conversions")) is ill-formed[.](#expr.cast-3.sentence-1)
[4](#expr.cast-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6877)
The conversions performed by
- [(4.1)](#expr.cast-4.1)
a const_cast ([[expr.const.cast]](#expr.const.cast "7.6.1.11Const cast")),
- [(4.2)](#expr.cast-4.2)
a static_cast ([[expr.static.cast]](#expr.static.cast "7.6.1.9Static cast")),
- [(4.3)](#expr.cast-4.3)
a static_cast followed by a const_cast,
- [(4.4)](#expr.cast-4.4)
a reinterpret_cast ([[expr.reinterpret.cast]](#expr.reinterpret.cast "7.6.1.10Reinterpret cast")), or
- [(4.5)](#expr.cast-4.5)
a reinterpret_cast followed by a const_cast,
can be performed using the cast notation of explicit type conversion[.](#expr.cast-4.sentence-1)
The same semantic restrictions and behaviors apply, with the exception
that in performing a static_cast in the following situations the
conversion is valid even if the base class is inaccessible:
- [(4.6)](#expr.cast-4.6)
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;
- [(4.7)](#expr.cast-4.7)
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;
- [(4.8)](#expr.cast-4.8)
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[.](#expr.cast-4.sentence-2)
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[.](#expr.cast-4.sentence-3)
If astatic_cast followed by a const_cast is used and
the conversion can be interpreted in more than one way as such,
the conversion is
ill-formed[.](#expr.cast-4.sentence-4)
[*Example [1](#expr.cast-example-1)*: struct A { };struct I1 : A { };struct I2 : A { };struct D : I1, I2 { };
A* foo( D* p ) {return (A*)( p ); // ill-formed static_cast interpretation}int*** ptr = 0;auto t = (int const*const*const*)ptr; // OK, const_cast interpretationstruct S {operator const int*(); operator volatile int*();};int *p = (int*)S(); // error: two possible interpretations using static_cast followed by const_cast — *end example*]
[5](#expr.cast-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6937)
The operand of a cast using the cast notation can be a prvalue of type
“pointer to incomplete class type”[.](#expr.cast-5.sentence-1)
The destination type of a cast
using the cast notation can be “pointer to incomplete class type”[.](#expr.cast-5.sentence-2)
If
both the operand and destination types are class types and one or both
are incomplete, it is unspecified whether the static_cast or thereinterpret_cast interpretation is used, even if there is an
inheritance relationship between the two classes[.](#expr.cast-5.sentence-3)
[*Note [2](#expr.cast-note-2)*:
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[.](#expr.cast-5.sentence-4)
— *end note*]
### [7.6.4](#expr.mptr.oper) Pointer-to-member operators [[expr.mptr.oper]](expr.mptr.oper)
[1](#expr.mptr.oper-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6956)
The pointer-to-member operators ->* and .* group
left-to-right[.](#expr.mptr.oper-1.sentence-1)
[pm-expression:](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")
[*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]") .* [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]") ->* [*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[2](#expr.mptr.oper-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6973)
The binary operator .* binds its second operand, which shall be
a prvalue
of type “pointer to member of T” to its first operand, which shall be
a glvalue
of
class T or of a class of which T is an unambiguous and
accessible base class[.](#expr.mptr.oper-2.sentence-1)
The result is an object or a function of the type
specified by the second operand[.](#expr.mptr.oper-2.sentence-2)
[3](#expr.mptr.oper-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6983)
The binary operator ->* binds its second operand, which shall be
a prvalue
of type “pointer to member of T” to its first operand, which shall be of
type “pointer to U”
where U is either T or
a class of which T is an unambiguous and accessible base class[.](#expr.mptr.oper-3.sentence-1)
The expression E1->*E2 is converted into the equivalent form(*(E1)).*E2[.](#expr.mptr.oper-3.sentence-2)
[4](#expr.mptr.oper-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6994)
Abbreviating [*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]").*[*cast-expression*](#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") as E1.*E2, E1 is called the [*object expression*](#def:object_expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")[.](#expr.mptr.oper-4.sentence-1)
If the result of E1 is an object
whose type is not similar to the type of E1, or
whose most derived object does not
contain the member to whichE2 refers, the behavior is undefined[.](#expr.mptr.oper-4.sentence-2)
The expression E1 is sequenced before the expression E2[.](#expr.mptr.oper-4.sentence-3)
[5](#expr.mptr.oper-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7004)
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 forE1.E2 given in [[expr.ref]](#expr.ref "7.6.1.5Class member access")[.](#expr.mptr.oper-5.sentence-1)
[*Note [1](#expr.mptr.oper-note-1)*:
It is not possible to use a pointer to member that refers to amutable member to modify a const class object[.](#expr.mptr.oper-5.sentence-2)
For
example,struct S { S() : i(0) { }mutable int i;};void f(){const S cs; int S::* pm = &S::i; // pm refers to mutable member S::i cs.*pm = 88; // error: cs is a const object}
— *end note*]
[6](#expr.mptr.oper-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7027)
If the result of .* or ->* is a function, then that
result can be used only as the operand for the function call operator()[.](#expr.mptr.oper-6.sentence-1)
[*Example [1](#expr.mptr.oper-example-1)*:
(ptr_to_obj->*ptr_to_mfct)(10); calls the member function denoted by ptr_to_mfct for the object
pointed to by ptr_to_obj[.](#expr.mptr.oper-6.sentence-2)
— *end example*]
In a .* expression whose object expression is an rvalue, the program is
ill-formed if the second operand is a pointer to member function
whose [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") is &,
unless its [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") is const[.](#expr.mptr.oper-6.sentence-3)
In a .* expression whose object expression is an lvalue, the program is ill-formed if the second
operand is
a pointer to member function
whose [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") is &&[.](#expr.mptr.oper-6.sentence-4)
The result of a .* 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[.](#expr.mptr.oper-6.sentence-5)
The result of a .* expression whose
second operand is a pointer to a member function is a prvalue[.](#expr.mptr.oper-6.sentence-6)
If the second operand is the [null member pointer value](conv.mem#def:value,null_member_pointer "7.3.13Pointer-to-member conversions[conv.mem]"),
the behavior is undefined[.](#expr.mptr.oper-6.sentence-7)
### [7.6.5](#expr.mul) Multiplicative operators [[expr.mul]](expr.mul)
[1](#expr.mul-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7059)
The multiplicative operators *, /, and % group
left-to-right[.](#expr.mul-1.sentence-1)
[multiplicative-expression:](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]")
[*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")
[*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]") * [*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")
[*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]") / [*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")
[*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]") % [*pm-expression*](#nt:pm-expression "7.6.4Pointer-to-member operators[expr.mptr.oper]")
[2](#expr.mul-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7079)
The operands of * and / shall have arithmetic or unscoped
enumeration type; the operands of % shall have integral or unscoped
enumeration type[.](#expr.mul-2.sentence-1)
The [usual arithmetic conversions](expr.arith.conv "7.4Usual arithmetic conversions[expr.arith.conv]") are performed on the
operands and determine the type of the result[.](#expr.mul-2.sentence-2)
[3](#expr.mul-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7085)
The binary * operator indicates multiplication[.](#expr.mul-3.sentence-1)
[4](#expr.mul-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7088)
The binary / operator yields the quotient, and the binary% operator yields the remainder from the division of the first
expression by the second[.](#expr.mul-4.sentence-1)
If the second operand of / or % is zero, the behavior is
undefined[.](#expr.mul-4.sentence-2)
For integral operands, the / operator yields the algebraic quotient with
any fractional part discarded;[63](#footnote-63 "This is often called truncation towards zero.") if the quotient a/b is representable in the type of the result,(a/b)*b + a%b is equal to a; otherwise, the behavior
of both a/b and a%b is undefined[.](#expr.mul-4.sentence-3)
[63)](#footnote-63)[63)](#footnoteref-63)
This is often called truncation towards zero[.](#footnote-63.sentence-1)
### [7.6.6](#expr.add) Additive operators [[expr.add]](expr.add)
[1](#expr.add-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7108)
The additive operators + and - group left-to-right[.](#expr.add-1.sentence-1)
Each operand shall be a prvalue[.](#expr.add-1.sentence-2)
If both operands have arithmetic or unscoped enumeration type,
the usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed[.](#expr.add-1.sentence-3)
Otherwise, if one operand has arithmetic or unscoped enumeration type,
integral promotion is applied ([[conv.prom]](conv.prom "7.3.7Integral promotions")) to that operand[.](#expr.add-1.sentence-4)
A converted or promoted operand is used in place of
the corresponding original operand for the remainder of this section[.](#expr.add-1.sentence-5)
[additive-expression:](#nt:additive-expression "7.6.6Additive operators[expr.add]")
[*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]")
[*additive-expression*](#nt:additive-expression "7.6.6Additive operators[expr.add]") + [*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]")
[*additive-expression*](#nt:additive-expression "7.6.6Additive operators[expr.add]") - [*multiplicative-expression*](#nt:multiplicative-expression "7.6.5Multiplicative operators[expr.mul]")
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[.](#expr.add-1.sentence-6)
[2](#expr.add-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7137)
For subtraction, one of the following shall hold:
- [(2.1)](#expr.add-2.1)
both operands have arithmetic type; or
- [(2.2)](#expr.add-2.2)
both operands are pointers to cv-qualified or cv-unqualified
versions of the same completely-defined object type; or
- [(2.3)](#expr.add-2.3)
the left operand is a pointer to a completely-defined object type
and the right operand has integral type[.](#expr.add-2.sentence-1)
[3](#expr.add-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7151)
The result of the binary + operator is the sum of the operands[.](#expr.add-3.sentence-1)
The result of the binary - operator is the difference resulting
from the subtraction of the second operand from the first[.](#expr.add-3.sentence-2)
[4](#expr.add-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7156)
When an expression J that has integral type
is added to or subtracted from an expression P of pointer type,
the result has the type of P[.](#expr.add-4.sentence-1)
- [(4.1)](#expr.add-4.1)
If P evaluates to a null pointer value andJ evaluates to 0, the result is a null pointer value[.](#expr.add-4.1.sentence-1)
- [(4.2)](#expr.add-4.2)
Otherwise, if P points to a (possibly-hypothetical) array element i of an array object x with n elements ([[dcl.array]](dcl.array "9.3.4.5Arrays")),[64](#footnote-64 "As specified in [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.") the expressions P + J and J + P (where J has the value j)
point to the (possibly-hypothetical) array elementi+j of x if 0≤i+j≤n and the expression P - J points to the (possibly-hypothetical) array elementi−j of x if 0≤i−‰¤n[.](#expr.add-4.2.sentence-1)
- [(4.3)](#expr.add-4.3)
Otherwise, the behavior is undefined[.](#expr.add-4.3.sentence-1)
[*Note [1](#expr.add-note-1)*:
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[.](#expr.add-4.sentence-2)
— *end note*]
[5](#expr.add-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7189)
When two pointer expressions P and Q are subtracted,
the type of the result is an implementation-defined signed
integral type; this type shall be the same type that is named bystd::ptrdiff_t in the [<cstddef>](cstddef.syn#header:%3ccstddef%3e "17.2.1Header <cstddef> synopsis[cstddef.syn]") header ([[support.types.layout]](support.types.layout "17.2.4Sizes, alignments, and offsets"))[.](#expr.add-5.sentence-1)
- [(5.1)](#expr.add-5.1)
If P and Q both evaluate to null pointer values,
the result is 0[.](#expr.add-5.1.sentence-1)
- [(5.2)](#expr.add-5.2)
Otherwise, if P and Q point to, respectively,
array elements i and j of the same array object x,
the expression P - Q has the value i−j[.](#expr.add-5.2.sentence-1)
[*Note [2](#expr.add-note-2)*:
If the value i−j is not in the range of representable values
of type std::ptrdiff_t,
the behavior is undefined ([[expr.pre]](expr.pre "7.1Preamble"))[.](#expr.add-5.2.sentence-2)
— *end note*]
- [(5.3)](#expr.add-5.3)
Otherwise, the behavior is undefined[.](#expr.add-5.3.sentence-1)
[6](#expr.add-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7215)
For addition or subtraction, if the expressions P or Q have
type “pointer to cv T”, where T and the array element type
are not [similar](conv.qual#def:similar_types "7.3.6Qualification conversions[conv.qual]"), the behavior is undefined[.](#expr.add-6.sentence-1)
[*Example [1](#expr.add-example-1)*: int arr[5] = {1, 2, 3, 4, 5};unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);unsigned int k = *p; // OK, value of k is 2 ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion"))unsigned int *q = p + 1; // undefined behavior: p points to an int, not an unsigned int object — *end example*]
[64)](#footnote-64)[64)](#footnoteref-64)
As specified in [[basic.compound]](basic.compound "6.9.4Compound types"),
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 elementn for this purpose[.](#footnote-64.sentence-1)
### [7.6.7](#expr.shift) Shift operators [[expr.shift]](expr.shift)
[1](#expr.shift-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7230)
The shift operators << and >> group left-to-right[.](#expr.shift-1.sentence-1)
[shift-expression:](#nt:shift-expression "7.6.7Shift operators[expr.shift]")
[*additive-expression*](#nt:additive-expression "7.6.6Additive operators[expr.add]")
[*shift-expression*](#nt:shift-expression "7.6.7Shift operators[expr.shift]") << [*additive-expression*](#nt:additive-expression "7.6.6Additive operators[expr.add]")
[*shift-expression*](#nt:shift-expression "7.6.7Shift operators[expr.shift]") >> [*additive-expression*](#nt:additive-expression "7.6.6Additive operators[expr.add]")
The operands shall be prvalues of integral or unscoped enumeration type and integral
promotions are performed[.](#expr.shift-1.sentence-2)
The type of the result is that of the promoted
left operand[.](#expr.shift-1.sentence-3)
The behavior is undefined if the right operand is negative, or greater
than or equal to the width of the promoted left operand[.](#expr.shift-1.sentence-4)
[2](#expr.shift-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7258)
The value of E1 << E2 is the unique value congruent toE1×2E2 modulo 2N,
where N is the width of the type of the result[.](#expr.shift-2.sentence-1)
[*Note [1](#expr.shift-note-1)*:
E1 is left-shifted E2 bit positions;
vacated bits are zero-filled[.](#expr.shift-2.sentence-2)
— *end note*]
[3](#expr.shift-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7267)
The value of E1 >> E2 is E1/2E2,
rounded towards negative infinity[.](#expr.shift-3.sentence-1)
[*Note [2](#expr.shift-note-2)*:
E1 is right-shifted E2 bit positions[.](#expr.shift-3.sentence-2)
Right-shift on signed integral types is an arithmetic right shift,
which performs sign-extension[.](#expr.shift-3.sentence-3)
— *end note*]
[4](#expr.shift-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7276)
The expression E1 is sequenced before the expression E2[.](#expr.shift-4.sentence-1)
### [7.6.8](#expr.spaceship) Three-way comparison operator [[expr.spaceship]](expr.spaceship)
[1](#expr.spaceship-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7283)
The three-way comparison operator groups left-to-right[.](#expr.spaceship-1.sentence-1)
[compare-expression:](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
[*shift-expression*](#nt:shift-expression "7.6.7Shift operators[expr.shift]")
[*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]") <=> [*shift-expression*](#nt:shift-expression "7.6.7Shift operators[expr.shift]")
[2](#expr.spaceship-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7296)
The expression p <=> q is a prvalue indicating whetherp is less than, equal to, greater than, or incomparable withq[.](#expr.spaceship-2.sentence-1)
[3](#expr.spaceship-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7301)
If one of the operands is of type bool and the other is not, the program is ill-formed[.](#expr.spaceship-3.sentence-1)
[4](#expr.spaceship-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7305)
If both operands have arithmetic types,
or one operand has integral type and
the other operand has unscoped enumeration type,
the [usual arithmetic conversions](expr.arith.conv "7.4Usual arithmetic conversions[expr.arith.conv]") are applied to the operands[.](#expr.spaceship-4.sentence-1)
Then:
- [(4.1)](#expr.spaceship-4.1)
If a [narrowing conversion](dcl.init.list#def:conversion,narrowing "9.5.5List-initialization[dcl.init.list]") is required,
other than from an integral type to a floating-point type,
the program is ill-formed[.](#expr.spaceship-4.1.sentence-1)
- [(4.2)](#expr.spaceship-4.2)
Otherwise, if the operands have integral type,
the result is of type std::strong_ordering[.](#expr.spaceship-4.2.sentence-1)
The result isstd::strong_ordering::equal if both operands are arithmetically equal,std::strong_ordering::less if the first operand is arithmetically
less than the second operand,
andstd::strong_ordering::greater otherwise[.](#expr.spaceship-4.2.sentence-2)
- [(4.3)](#expr.spaceship-4.3)
Otherwise, the operands have floating-point type, and
the result is of type std::partial_ordering[.](#expr.spaceship-4.3.sentence-1)
The expression a <=> b yieldsstd::partial_ordering::less if a is less than b,std::partial_ordering::greater if a is greater than b,std::partial_ordering::equivalent if a is equivalent to b,
andstd::partial_ordering::unordered otherwise[.](#expr.spaceship-4.3.sentence-2)
[5](#expr.spaceship-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7343)
If both operands have the same enumeration type E,
the operator yields the result of
converting the operands to the underlying type of E and applying <=> to the converted operands[.](#expr.spaceship-5.sentence-1)
[6](#expr.spaceship-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7349)
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 ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")),
pointer conversions ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")),
and[qualification conversions](conv.qual "7.3.6Qualification conversions[conv.qual]") are performed on both operands
to bring them to their composite pointer type ([[expr.type]](expr.type "7.2.2Type"))[.](#expr.spaceship-6.sentence-1)
After the conversions, the operands shall have the same type[.](#expr.spaceship-6.sentence-2)
[*Note [1](#expr.spaceship-note-1)*:
If both of the operands are arrays,[array-to-pointer conversions](conv.array "7.3.3Array-to-pointer conversion[conv.array]") are not applied[.](#expr.spaceship-6.sentence-3)
— *end note*]
In this case,p <=> q is of type std::strong_ordering and
the result is defined by the following rules:
- [(6.1)](#expr.spaceship-6.1)
If two pointer operands p and q compare equal ([[expr.eq]](#expr.eq "7.6.10Equality operators")),p <=> q yields std::strong_ordering::equal;
- [(6.2)](#expr.spaceship-6.2)
otherwise, if p and q compare unequal,p <=> q yieldsstd::strong_ordering::less if q compares greater than p andstd::strong_ordering::greater if p compares greater than q ([[expr.rel]](#expr.rel "7.6.9Relational operators"));
- [(6.3)](#expr.spaceship-6.3)
otherwise, the result is unspecified[.](#expr.spaceship-6.sentence-4)
[7](#expr.spaceship-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7382)
Otherwise, the program is ill-formed[.](#expr.spaceship-7.sentence-1)
[8](#expr.spaceship-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7385)
The three comparison category types ([[cmp.categories]](cmp.categories "17.12.2Comparison category types"))
(the typesstd::strong_ordering,std::weak_ordering, andstd::partial_ordering)
are not predefined;
if a standard library declaration ([[compare.syn]](compare.syn "17.12.1Header <compare> synopsis"), [[std.modules]](std.modules "16.4.2.4Modules"))
of such a class type does not precede ([[basic.lookup.general]](basic.lookup.general "6.5.1General"))
a use of that type —
even an implicit use in which the type is not named
(e.g., via the auto specifier ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
in a defaulted three-way comparison ([[class.spaceship]](class.spaceship "11.10.3Three-way comparison"))
or use of the built-in operator) — the program is ill-formed[.](#expr.spaceship-8.sentence-1)
### [7.6.9](#expr.rel) Relational operators [[expr.rel]](expr.rel)
[1](#expr.rel-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7404)
The relational operators group left-to-right[.](#expr.rel-1.sentence-1)
[*Example [1](#expr.rel-example-1)*:
a<b<c means (a<b)<c and not(a<b)&&(b<c)[.](#expr.rel-1.sentence-2)
— *end example*]
[relational-expression:](#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
[*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]") < [*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
[*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]") > [*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
[*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]") <= [*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
[*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]") >= [*compare-expression*](#nt:compare-expression "7.6.8Three-way comparison operator[expr.spaceship]")
The
lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion"))
and function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion"))
standard conversions are performed on the operands[.](#expr.rel-1.sentence-3)
If one of the operands is a pointer, the
array-to-pointer conversion ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")) is performed on the other operand[.](#expr.rel-1.sentence-4)
[2](#expr.rel-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7435)
The converted operands shall have arithmetic, enumeration, or pointer type[.](#expr.rel-2.sentence-1)
The
operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all
yield false or true[.](#expr.rel-2.sentence-2)
The type of the result isbool[.](#expr.rel-2.sentence-3)
[3](#expr.rel-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7443)
The usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed on operands of arithmetic
or enumeration type[.](#expr.rel-3.sentence-1)
If both converted operands are pointers,
pointer conversions ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")),
function pointer conversions ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions")), and
qualification conversions ([[conv.qual]](conv.qual "7.3.6Qualification conversions"))
are performed to bring
them to their [composite pointer type](expr.type#def:composite_pointer_type "7.2.2Type[expr.type]")[.](#expr.rel-3.sentence-2)
After conversions, the operands shall have the same type[.](#expr.rel-3.sentence-3)
[4](#expr.rel-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7453)
The result of comparing unequal pointers to objects[65](#footnote-65 "As specified in [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.") is defined in terms of a partial order consistent with the following rules:
- [(4.1)](#expr.rel-4.1)
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[.](#expr.rel-4.1.sentence-1)
- [(4.2)](#expr.rel-4.2)
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[.](#expr.rel-4.2.sentence-1)
- [(4.3)](#expr.rel-4.3)
Otherwise, neither pointer is required to compare greater than the other[.](#expr.rel-4.3.sentence-1)
[5](#expr.rel-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7479)
If two operands p and q compare equal ([[expr.eq]](#expr.eq "7.6.10Equality operators")),p<=q and p>=q both yield true and p<q andp>q both yield false[.](#expr.rel-5.sentence-1)
Otherwise, if a pointer to object p compares greater than a pointer q, p>=q, p>q,q<=p, and q<p all yield true and p<=q,p<q, q>=p, and q>p all yield false[.](#expr.rel-5.sentence-2)
Otherwise, the result of each of the operators is unspecified[.](#expr.rel-5.sentence-3)
[*Note [1](#expr.rel-note-1)*:
A relational operator applied
to unequal function pointers
yields an unspecified result[.](#expr.rel-5.sentence-4)
A pointer value of type “pointer to cv void”
can point to an object ([[basic.compound]](basic.compound "6.9.4Compound types"))[.](#expr.rel-5.sentence-5)
— *end note*]
[6](#expr.rel-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7495)
If both operands (after conversions) are of arithmetic or enumeration type, each
of the operators shall yield true if the specified relationship is true
and false if it is false[.](#expr.rel-6.sentence-1)
[65)](#footnote-65)[65)](#footnoteref-65)
As specified in [[basic.compound]](basic.compound "6.9.4Compound types"),
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 elementn for this purpose[.](#footnote-65.sentence-1)
### [7.6.10](#expr.eq) Equality operators [[expr.eq]](expr.eq)
[equality-expression:](#nt:equality-expression "7.6.10Equality operators[expr.eq]")
[*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]") == [*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]") != [*relational-expression*](#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[1](#expr.eq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7512)
The == (equal to) and the != (not equal to) operators
group left-to-right[.](#expr.eq-1.sentence-1)
The
lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion"))
and function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion"))
standard conversions are performed on the operands[.](#expr.eq-1.sentence-2)
If one of the operands is a pointer or a null pointer constant ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")),
the array-to-pointer conversion ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")) is performed
on the other operand[.](#expr.eq-1.sentence-3)
[2](#expr.eq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7523)
The converted operands shall have scalar type[.](#expr.eq-2.sentence-1)
The operators== and != both yield true or false, i.e., a
result of type bool[.](#expr.eq-2.sentence-2)
In each case below, the operands shall have the
same type after the specified conversions have been applied[.](#expr.eq-2.sentence-3)
[3](#expr.eq-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7529)
If at least one of the converted operands is a pointer,[pointer conversions](conv.ptr "7.3.12Pointer conversions[conv.ptr]"),[function pointer conversions](conv.fctptr "7.3.14Function pointer conversions[conv.fctptr]"), and[qualification conversions](conv.qual "7.3.6Qualification conversions[conv.qual]") are performed on both operands to bring them to their [composite pointer type](expr.type#def:composite_pointer_type "7.2.2Type[expr.type]")[.](#expr.eq-3.sentence-1)
Comparing pointers is defined as follows:
- [(3.1)](#expr.eq-3.1)
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,[66](#footnote-66 "As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose.") the result of the comparison is unspecified[.](#expr.eq-3.1.sentence-1)
- [(3.2)](#expr.eq-3.2)
Otherwise, if the pointers are both null, both point to the samefunction, or both[represent the same address](basic.compound#def:represents_the_address "6.9.4Compound types[basic.compound]"),
they compare equal[.](#expr.eq-3.2.sentence-1)
- [(3.3)](#expr.eq-3.3)
Otherwise, the pointers compare unequal[.](#expr.eq-3.3.sentence-1)
[4](#expr.eq-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7559)
If at least one of the operands is a pointer to member,
pointer-to-member conversions ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions")),
function pointer conversions ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions")), and
qualification conversions ([[conv.qual]](conv.qual "7.3.6Qualification conversions"))
are performed on both operands to bring them to
their composite pointer type ([[expr.type]](expr.type "7.2.2Type"))[.](#expr.eq-4.sentence-1)
Comparing pointers to members is defined as follows:
- [(4.1)](#expr.eq-4.1)
If two pointers to members are both the null member pointer value, they compare
equal[.](#expr.eq-4.1.sentence-1)
- [(4.2)](#expr.eq-4.2)
If only one of two pointers to members is the null member pointer value, they
compare unequal[.](#expr.eq-4.2.sentence-1)
- [(4.3)](#expr.eq-4.3)
If either is a pointer to a virtual member function, the result is unspecified[.](#expr.eq-4.3.sentence-1)
- [(4.4)](#expr.eq-4.4)
If one refers to a member of class C1 and the other refers to a member
of a different class C2, where neither is a base class of the other,
the result is unspecified[.](#expr.eq-4.4.sentence-1)
[*Example [1](#expr.eq-example-1)*: 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 example*]
- [(4.5)](#expr.eq-4.5)
If both refer to (possibly different) members of the same [union](class.union "11.5Unions[class.union]"),
they compare equal[.](#expr.eq-4.5.sentence-1)
- [(4.6)](#expr.eq-4.6)
Otherwise, two pointers to members compare equal if they would refer to the same member of
the same [most derived object](intro.object#def:most_derived_object "6.8.2Object model[intro.object]") or the same subobject if
indirection with a hypothetical object of the associated
class type were performed, otherwise they compare unequal[.](#expr.eq-4.6.sentence-1)
[*Example [2](#expr.eq-example-2)*: 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); // falsebool y = (pb == pl); // true — *end example*]
[5](#expr.eq-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7625)
Two operands of type std::nullptr_t or one operand of typestd::nullptr_t and the other a null pointer constant compare equal[.](#expr.eq-5.sentence-1)
[6](#expr.eq-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7629)
If both operands are of type std::meta::info,
they compare equal if both operands
- [(6.1)](#expr.eq-6.1)
are null reflection values,
- [(6.2)](#expr.eq-6.2)
represent values that are template-argument-equivalent ([[temp.type]](temp.type "13.6Type equivalence")),
- [(6.3)](#expr.eq-6.3)
represent the same object,
- [(6.4)](#expr.eq-6.4)
represent the same entity,
- [(6.5)](#expr.eq-6.5)
represent the same annotation ([[dcl.attr.annotation]](dcl.attr.annotation "9.13.12Annotations")),
- [(6.6)](#expr.eq-6.6)
represent the same direct base class relationship, or
- [(6.7)](#expr.eq-6.7)
represent equal data member descriptions ([[class.mem.general]](class.mem.general "11.4.1General")),
and they compare unequal otherwise[.](#expr.eq-6.sentence-1)
[7](#expr.eq-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7643)
If two operands compare equal, the result is true for
the == operator and false for the != operator[.](#expr.eq-7.sentence-1)
If two operands
compare unequal, the result is false for the == operator andtrue for the != operator[.](#expr.eq-7.sentence-2)
Otherwise, the result of each of the
operators is unspecified[.](#expr.eq-7.sentence-3)
[8](#expr.eq-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7650)
If both operands are of arithmetic or enumeration type, the usual arithmetic
conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed on both operands; each of the operators shall yieldtrue if the specified relationship is true and false if it is
false[.](#expr.eq-8.sentence-1)
[66)](#footnote-66)[66)](#footnoteref-66)
As specified in [[basic.compound]](basic.compound "6.9.4Compound types"),
an object that is not an array element is
considered to belong to a single-element array for this purpose[.](#footnote-66.sentence-1)
### [7.6.11](#expr.bit.and) Bitwise AND operator [[expr.bit.and]](expr.bit.and)
[and-expression:](#nt:and-expression "7.6.11Bitwise AND operator[expr.bit.and]")
[*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]")
[*and-expression*](#nt:and-expression "7.6.11Bitwise AND operator[expr.bit.and]") & [*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]")
[1](#expr.bit.and-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7668)
The & operator groups left-to-right[.](#expr.bit.and-1.sentence-1)
The operands shall be of integral or unscoped enumeration type[.](#expr.bit.and-1.sentence-2)
The usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed[.](#expr.bit.and-1.sentence-3)
Given the coefficients xi and yi of the base-2 representation ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
of the converted operands x and y,
the coefficient ri of the base-2 representation of the result r is 1 if both xi and yi are 1, and 0 otherwise[.](#expr.bit.and-1.sentence-4)
[*Note [1](#expr.bit.and-note-1)*:
The result is the bitwise and function of the operands[.](#expr.bit.and-1.sentence-5)
— *end note*]
### [7.6.12](#expr.xor) Bitwise exclusive OR operator [[expr.xor]](expr.xor)
[exclusive-or-expression:](#nt:exclusive-or-expression "7.6.12Bitwise exclusive OR operator[expr.xor]")
[*and-expression*](#nt:and-expression "7.6.11Bitwise AND operator[expr.bit.and]")
[*exclusive-or-expression*](#nt:exclusive-or-expression "7.6.12Bitwise exclusive OR operator[expr.xor]") ^ [*and-expression*](#nt:and-expression "7.6.11Bitwise AND operator[expr.bit.and]")
[1](#expr.xor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7693)
The ^ operator groups left-to-right[.](#expr.xor-1.sentence-1)
The operands shall be of integral or unscoped enumeration type[.](#expr.xor-1.sentence-2)
The usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed[.](#expr.xor-1.sentence-3)
Given the coefficients xi and yi of the base-2 representation ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
of the converted operands x and y,
the coefficient ri of the base-2 representation of the result r is 1 if either (but not both) of xi and yi is 1,
and 0 otherwise[.](#expr.xor-1.sentence-4)
[*Note [1](#expr.xor-note-1)*:
The result is the bitwise exclusive or function of the operands[.](#expr.xor-1.sentence-5)
— *end note*]
### [7.6.13](#expr.or) Bitwise inclusive OR operator [[expr.or]](expr.or)
[inclusive-or-expression:](#nt:inclusive-or-expression "7.6.13Bitwise inclusive OR operator[expr.or]")
[*exclusive-or-expression*](#nt:exclusive-or-expression "7.6.12Bitwise exclusive OR operator[expr.xor]")
[*inclusive-or-expression*](#nt:inclusive-or-expression "7.6.13Bitwise inclusive OR operator[expr.or]") | [*exclusive-or-expression*](#nt:exclusive-or-expression "7.6.12Bitwise exclusive OR operator[expr.xor]")
[1](#expr.or-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7719)
The | operator groups left-to-right[.](#expr.or-1.sentence-1)
The operands shall be of integral or unscoped enumeration type[.](#expr.or-1.sentence-2)
The usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4Usual arithmetic conversions")) are performed[.](#expr.or-1.sentence-3)
Given the coefficients xi and yi of the base-2 representation ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
of the converted operands x and y,
the coefficient ri of the base-2 representation of the result r is 1 if at least one of xi and yi is 1, and 0 otherwise[.](#expr.or-1.sentence-4)
[*Note [1](#expr.or-note-1)*:
The result is the bitwise inclusive or function of the operands[.](#expr.or-1.sentence-5)
— *end note*]
### [7.6.14](#expr.log.and) Logical AND operator [[expr.log.and]](expr.log.and)
[logical-and-expression:](#nt:logical-and-expression "7.6.14Logical AND operator[expr.log.and]")
[*inclusive-or-expression*](#nt:inclusive-or-expression "7.6.13Bitwise inclusive OR operator[expr.or]")
[*logical-and-expression*](#nt:logical-and-expression "7.6.14Logical AND operator[expr.log.and]") && [*inclusive-or-expression*](#nt:inclusive-or-expression "7.6.13Bitwise inclusive OR operator[expr.or]")
[1](#expr.log.and-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7744)
The && operator groups left-to-right[.](#expr.log.and-1.sentence-1)
The operands are both
contextually converted to bool ([[conv]](conv "7.3Standard conversions"))[.](#expr.log.and-1.sentence-2)
The
result is true if both operands are true andfalse otherwise[.](#expr.log.and-1.sentence-3)
Unlike &, && guarantees
left-to-right evaluation: the second operand is not evaluated if the
first operand is false[.](#expr.log.and-1.sentence-4)
[2](#expr.log.and-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7753)
The result is a bool[.](#expr.log.and-2.sentence-1)
If the second expression is evaluated,
the first expression is sequenced before
the second expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.log.and-2.sentence-2)
### [7.6.15](#expr.log.or) Logical OR operator [[expr.log.or]](expr.log.or)
[logical-or-expression:](#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]")
[*logical-and-expression*](#nt:logical-and-expression "7.6.14Logical AND operator[expr.log.and]")
[*logical-or-expression*](#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]") || [*logical-and-expression*](#nt:logical-and-expression "7.6.14Logical AND operator[expr.log.and]")
[1](#expr.log.or-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7771)
The || operator groups left-to-right[.](#expr.log.or-1.sentence-1)
The operands are both
contextually converted to bool ([[conv]](conv "7.3Standard conversions"))[.](#expr.log.or-1.sentence-2)
The result istrue if either of its operands is true, andfalse otherwise[.](#expr.log.or-1.sentence-3)
Unlike |, || guarantees
left-to-right evaluation; moreover, the second operand is not evaluated
if the first operand evaluates to true[.](#expr.log.or-1.sentence-4)
[2](#expr.log.or-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7780)
The result is a bool[.](#expr.log.or-2.sentence-1)
If the second expression is evaluated,
the first expression is sequenced before
the second expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.log.or-2.sentence-2)
### [7.6.16](#expr.cond) Conditional operator [[expr.cond]](expr.cond)
[conditional-expression:](#nt:conditional-expression "7.6.16Conditional operator[expr.cond]")
[*logical-or-expression*](#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]")
[*logical-or-expression*](#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]") ? [*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") : [*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
[1](#expr.cond-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7798)
Conditional expressions group right-to-left[.](#expr.cond-1.sentence-1)
The first expression is
contextually converted to bool ([[conv]](conv "7.3Standard conversions"))[.](#expr.cond-1.sentence-2)
It is
evaluated and if it is true, the result of the conditional
expression is the value of the second expression, otherwise that of the
third expression[.](#expr.cond-1.sentence-3)
Only one of the second and third expressions is
evaluated[.](#expr.cond-1.sentence-4)
The first expression is sequenced before
the second or third expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.cond-1.sentence-5)
[2](#expr.cond-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7809)
If either the second or the third operand has type void,
one of the following shall hold:
- [(2.1)](#expr.cond-2.1)
The second or the third operand (but not both) is a (possibly
parenthesized) [*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") ([[expr.throw]](#expr.throw "7.6.18Throwing an exception")); the result
is of the type and value category of the other[.](#expr.cond-2.1.sentence-1)
The [*conditional-expression*](#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") is a bit-field if that operand is a bit-field[.](#expr.cond-2.1.sentence-2)
- [(2.2)](#expr.cond-2.2)
Both the second and the third operands have type void; the
result is of type void and is a prvalue[.](#expr.cond-2.2.sentence-1)
[*Note [1](#expr.cond-note-1)*:
This
includes the case where both operands are [*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]")*s*[.](#expr.cond-2.2.sentence-2)
— *end note*]
[3](#expr.cond-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7829)
Otherwise, if the second and third operand are glvalue bit-fields
of the same value category and
of types *cv1* T and *cv2* T, respectively,
the operands are considered to be of type cv T for the remainder of this subclause,
where cv is the union of *cv1* and *cv2*[.](#expr.cond-3.sentence-1)
[4](#expr.cond-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7837)
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](over.best.ics "12.2.4.2Implicit conversion sequences[over.best.ics]") from
each of those operands to the type of the other[.](#expr.cond-4.sentence-1)
[*Note [2](#expr.cond-note-2)*:
Properties such as access, whether an operand is a bit-field, or whether
a conversion function is deleted are ignored for that determination[.](#expr.cond-4.sentence-2)
— *end note*]
Attempts are made to form an implicit conversion sequence
from an operand expression E1 of type T1 to a target type related to the type T2 of the operand expression E2 as follows:
- [(4.1)](#expr.cond-4.1)
If E2 is an lvalue, the target type is
“lvalue reference to T2”,
but an implicit conversion sequence can only be formed
if the reference would bind directly ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))
to a glvalue[.](#expr.cond-4.1.sentence-1)
- [(4.2)](#expr.cond-4.2)
If E2 is an xvalue, the target type is
“rvalue reference to T2”,
but an implicit conversion sequence can only be formed
if the reference would bind directly[.](#expr.cond-4.2.sentence-1)
- [(4.3)](#expr.cond-4.3)
If 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:
* [(4.3.1)](#expr.cond-4.3.1)
if T1 and T2 are the same class type
(ignoring cv-qualification):
+
[(4.3.1.1)](#expr.cond-4.3.1.1)
if T2 is at least as cv-qualified as T1,
the target type is T2,
+
[(4.3.1.2)](#expr.cond-4.3.1.2)
otherwise, no conversion sequence is formed for this operand;
* [(4.3.2)](#expr.cond-4.3.2)
otherwise, if T2 is a base class of T1,
the target type is *cv1* T2, where *cv1* denotes the cv-qualifiers of T1;
* [(4.3.3)](#expr.cond-4.3.3)
otherwise, the target type is the type that E2 would have
after applying the[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"),[array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"), and[function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions[.](#expr.cond-4.3.sentence-1)
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:
- [(4.4)](#expr.cond-4.4)
If both sequences can be formed, or one can be formed but it is the
ambiguous conversion sequence, the program is ill-formed[.](#expr.cond-4.4.sentence-1)
- [(4.5)](#expr.cond-4.5)
If no conversion sequence can be formed, the operands are left unchanged
and further checking is performed as described below[.](#expr.cond-4.5.sentence-1)
- [(4.6)](#expr.cond-4.6)
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[.](#expr.cond-4.6.sentence-1)
[*Note [3](#expr.cond-note-3)*:
The conversion might be ill-formed even if an implicit conversion
sequence could be formed[.](#expr.cond-4.6.sentence-2)
— *end note*]
[5](#expr.cond-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7909)
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[.](#expr.cond-5.sentence-1)
[6](#expr.cond-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7915)
Otherwise, the result is a prvalue[.](#expr.cond-6.sentence-1)
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 ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions"), [[over.built]](over.built "12.5Built-in operators"))[.](#expr.cond-6.sentence-2)
If the overload resolution fails, the program is ill-formed[.](#expr.cond-6.sentence-3)
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[.](#expr.cond-6.sentence-4)
[7](#expr.cond-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7925)
[Array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]") and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions are
performed on the second and third operands[.](#expr.cond-7.sentence-1)
After those conversions, one
of the following shall hold:
- [(7.1)](#expr.cond-7.1)
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[.](#expr.cond-7.1.sentence-1)
- [(7.2)](#expr.cond-7.2)
The second and third operands have arithmetic or enumeration type;
the [usual arithmetic conversions](expr.arith.conv "7.4Usual arithmetic conversions[expr.arith.conv]") are performed to bring them to a common
type, and the result is of that type[.](#expr.cond-7.2.sentence-1)
- [(7.3)](#expr.cond-7.3)
One or both of the second and third operands have pointer type;[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"),[pointer](conv.ptr "7.3.12Pointer conversions[conv.ptr]"),[function pointer](conv.fctptr "7.3.14Function pointer conversions[conv.fctptr]"), and[qualification conversions](conv.qual "7.3.6Qualification conversions[conv.qual]") are performed to bring them to their[composite pointer type](expr.type#def:composite_pointer_type "7.2.2Type[expr.type]")[.](#expr.cond-7.3.sentence-1)
The result is of the composite
pointer type[.](#expr.cond-7.3.sentence-2)
- [(7.4)](#expr.cond-7.4)
One or both of the second and third operands have pointer-to-member type;
lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")),
pointer to member ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions")),
function pointer ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions")), and
qualification conversions ([[conv.qual]](conv.qual "7.3.6Qualification conversions"))
are performed to bring them to their composite
pointer type ([[expr.type]](expr.type "7.2.2Type"))[.](#expr.cond-7.4.sentence-1)
The result is of the composite pointer type[.](#expr.cond-7.4.sentence-2)
- [(7.5)](#expr.cond-7.5)
Both the second and third operands have type std::nullptr_t or one has
that type and the other is a null pointer constant[.](#expr.cond-7.5.sentence-1)
The result is of typestd::nullptr_t[.](#expr.cond-7.5.sentence-2)
### [7.6.17](#expr.yield) Yielding a value [[expr.yield]](expr.yield)
[yield-expression:](#nt:yield-expression "7.6.17Yielding a value[expr.yield]")
co_yield [*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
co_yield [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[1](#expr.yield-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7971)
A [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") shall appear only within a suspension context
of a function ([[expr.await]](#expr.await "7.6.2.4Await"))[.](#expr.yield-1.sentence-1)
Let *e* be the operand of the [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") and*p* be an lvalue naming the promise object of the enclosing
coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions")), then the [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") is equivalent to the expressionco_await *p*.yield_value(*e*)[.](#expr.yield-1.sentence-2)
[*Example [1](#expr.yield-example-1)*: template <typename T>struct my_generator {struct promise_type { T current_value; /* ... */auto yield_value(T v) { current_value = std::move(v); return std::suspend_always{}; }}; struct iterator { /* ... */ };
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: [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") outside of function suspension contextint a[] = { co_yield 1 }; // error: [*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]") outside of function suspension contextint main() {auto r1 = g1(); auto r2 = g2();
assert(std::equal(r1.begin(), r1.end(), r2.begin(), r2.end()));} — *end example*]
### [7.6.18](#expr.throw) Throwing an exception [[expr.throw]](expr.throw)
[throw-expression:](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]")
throw [*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")opt
[1](#expr.throw-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8025)
A [*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") is of type void[.](#expr.throw-1.sentence-1)
[2](#expr.throw-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8028)
A [*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") with an operand throws an
exception ([[except.throw]](except.throw "14.2Throwing an exception"))[.](#expr.throw-2.sentence-1)
The array-to-pointer ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")) and function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion"))
standard conversions are performed on the operand[.](#expr.throw-2.sentence-2)
The type of the exception object is determined by removing
any top-level [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* from the type of the
(possibly converted) operand[.](#expr.throw-2.sentence-3)
The exception object is copy-initialized ([[dcl.init.general]](dcl.init.general "9.5.1General"))
from the (possibly converted) operand[.](#expr.throw-2.sentence-4)
[3](#expr.throw-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8039)
A[*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") with no operand rethrows the currently handled exception ([[except.handle]](except.handle "14.4Handling an exception"))[.](#expr.throw-3.sentence-1)
If no exception is presently being handled,
the function std::terminate is invoked ([[except.terminate]](except.terminate "14.6.2The std::terminate function"))[.](#expr.throw-3.sentence-2)
Otherwise, the exception is reactivated with the existing exception object;
no new exception object is created[.](#expr.throw-3.sentence-3)
The exception is no longer considered to be caught[.](#expr.throw-3.sentence-4)
[*Example [1](#expr.throw-example-1)*:
An exception handler that cannot completely handle the exception itself
can be written like this:try {// ...} catch (...) { // catch all exceptions// respond (partially) to exceptionthrow; // pass the exception to some other handler}
— *end example*]
### [7.6.19](#expr.assign) Assignment and compound assignment operators [[expr.assign]](expr.assign)
[1](#expr.assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8067)
The assignment operator (=) and the compound assignment
operators all group right-to-left[.](#expr.assign-1.sentence-1)
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[.](#expr.assign-1.sentence-2)
The result in all cases is a bit-field if
the left operand is a bit-field[.](#expr.assign-1.sentence-3)
In all cases, the assignment is
sequenced after thevalue computation of the right and left operands,
and before the
value computation of the assignment expression[.](#expr.assign-1.sentence-4)
The right operand is sequenced before the left operand[.](#expr.assign-1.sentence-5)
With
respect to an indeterminately-sequenced function call, the operation of
a compound assignment is a single evaluation[.](#expr.assign-1.sentence-6)
[*Note [1](#expr.assign-note-1)*:
Therefore, a function call cannot intervene between the
lvalue-to-rvalue conversion and the side effect associated with any
single compound assignment operator[.](#expr.assign-1.sentence-7)
— *end note*]
[assignment-expression:](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
[*conditional-expression*](#nt:conditional-expression "7.6.16Conditional operator[expr.cond]")
[*yield-expression*](#nt:yield-expression "7.6.17Yielding a value[expr.yield]")
[*throw-expression*](#nt:throw-expression "7.6.18Throwing an exception[expr.throw]")
[*logical-or-expression*](#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]") [*assignment-operator*](#nt:assignment-operator "7.6.19Assignment and compound assignment operators[expr.assign]") [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")
[assignment-operator:](#nt:assignment-operator "7.6.19Assignment and compound assignment operators[expr.assign]") one of
= *= /= %= += -= >>= <<= &= ^= |=
[2](#expr.assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8115)
In simple assignment (=),
let V be the result of the right operand;
the object referred to by the left operand is
modified ([[defns.access]](defns.access "3.1access")) by replacing its value
with V or,
if the object is of integer type,
with the value congruent ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types")) to V[.](#expr.assign-2.sentence-1)
[3](#expr.assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8124)
If the right operand is an expression, it is implicitly[converted](conv "7.3Standard conversions[conv]") to the cv-unqualified type of the left
operand[.](#expr.assign-3.sentence-1)
[4](#expr.assign-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8130)
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 isimplementation-defined[.](#expr.assign-4.sentence-1)
[5](#expr.assign-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8137)
An assignment whose left operand is of
a volatile-qualified type is deprecated ([[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types"))
unless the (possibly parenthesized) assignment is a discarded-value expression or
an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]")[.](#expr.assign-5.sentence-1)
[6](#expr.assign-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8143)
The behavior of an expression of the form E1 *op*= E2 is equivalent to E1 = E1 *op* E2 except
that E1 is evaluated only once[.](#expr.assign-6.sentence-1)
[*Note [2](#expr.assign-note-2)*:
The object designated by E1 is accessed twice[.](#expr.assign-6.sentence-2)
— *end note*]
For += and -=,E1 shall either have arithmetic type or be a pointer to a
possibly cv-qualified completely-defined object type[.](#expr.assign-6.sentence-3)
In all other
cases, E1 shall have arithmetic type[.](#expr.assign-6.sentence-4)
[7](#expr.assign-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8155)
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[.](#expr.assign-7.sentence-1)
[*Note [3](#expr.assign-note-3)*:
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[.](#expr.assign-7.sentence-2)
See [[basic.lval]](basic.lval "7.2.1Value category")[.](#expr.assign-7.sentence-3)
— *end note*]
[8](#expr.assign-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8167)
A [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") B may appear on the right-hand side of
- [(8.1)](#expr.assign-8.1)
an assignment to a scalar of type T, in which case B shall have at most a single element[.](#expr.assign-8.1.sentence-1)
The meaning of x = B is x = t,
where t is an invented temporary variable
declared and initialized as T t = B[.](#expr.assign-8.1.sentence-2)
- [(8.2)](#expr.assign-8.2)
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 ([[over.assign]](over.assign "12.4.3.2Simple assignment"), [[over.match]](over.match "12.2Overload resolution"))[.](#expr.assign-8.2.sentence-1)
[*Example [1](#expr.assign-example-1)*: complex<double> z;
z = { 1,2 }; // meaning z.operator=({1,2}) z += { 1, 2 }; // meaning z.operator+=({1,2})int a, b;
a = b = { 1 }; // meaning a=b=1; a = { 1 } = b; // syntax error — *end example*]
### [7.6.20](#expr.comma) Comma operator [[expr.comma]](expr.comma)
[1](#expr.comma-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8202)
The comma operator groups left-to-right[.](#expr.comma-1.sentence-1)
[expression:](#nt:expression "7.6.20Comma operator[expr.comma]")
[*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
[*expression*](#nt:expression "7.6.20Comma operator[expr.comma]") , [*assignment-expression*](#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
A pair of expressions separated by a comma is evaluated left-to-right;
the left expression is
a [discarded-value expression](expr.prop#def:discarded-value_expression "7.2Properties of expressions[expr.prop]")[.](#expr.comma-1.sentence-2)
The left expression is sequenced before
the right expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#expr.comma-1.sentence-3)
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[.](#expr.comma-1.sentence-4)
[2](#expr.comma-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L8222)
[*Note [1](#expr.comma-note-1)*:
In contexts where the comma token is given special meaning
(e.g., function calls ([[expr.call]](#expr.call "7.6.1.3Function call")),
subscript expressions ([[expr.sub]](#expr.sub "7.6.1.2Subscripting")),
lists of initializers ([[dcl.init]](dcl.init "9.5Initializers")),
or [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")*s* ([[temp.names]](temp.names "13.3Names of template specializations"))),
the comma operator as described in this subclause can appear only in parentheses[.](#expr.comma-2.sentence-1)
[*Example [1](#expr.comma-example-1)*:
f(a, (t=3, t+2), c); has three arguments, the second of which has the value5[.](#expr.comma-2.sentence-2)
— *end example*]
— *end note*]