[expr.unary]
# 7 Expressions [[expr]](./#expr)
## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.unary)
### 7.6.2 Unary expressions [expr.unary]
#### [7.6.2.1](#general) General [[expr.unary.general]](expr.unary.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5167)
Expressions with unary operators group right-to-left[.](#general-1.sentence-1)
[unary-expression:](#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]")
[*unary-operator*](#nt:unary-operator "7.6.2.1 General [expr.unary.general]") [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
++ [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
-- [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
[*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]")
sizeof [*unary-expression*](#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
[*noexcept-expression*](#nt:noexcept-expression "7.6.2.7 noexcept operator [expr.unary.noexcept]")
[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")
[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]")
[*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")
[unary-operator:](#nt:unary-operator "7.6.2.1 General [expr.unary.general]") one of
* & + - ! ~
#### [7.6.2.2](#op) Unary operators [[expr.unary.op]](expr.unary.op)
[1](#op-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5219)
The unary * operator performs [*indirection*](#def:indirection "7.6.2.2 Unary operators [expr.unary.op]")[.](#op-1.sentence-1)
Its operand shall be a prvalue of type âpointer to Tâ,
where T is an object or function type[.](#op-1.sentence-2)
The operator yields an lvalue of type T[.](#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.8 Type identification")[.](#op-1.sentence-4)
[*Note [1](#op-note-1)*:
Indirection through a pointer to an out-of-lifetime object is valid ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#op-1.sentence-5)
â *end note*]
[*Note [2](#op-note-2)*:
Indirection through a pointer to an incomplete type (other thancv void) is valid[.](#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.2 Lvalue-to-rvalue conversion")[.](#op-1.sentence-7)
â *end note*]
[2](#op-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5241)
Each of the following unary operators yields a prvalue[.](#op-2.sentence-1)
[3](#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[.](#op-3.sentence-1)
- [(3.1)](#op-3.1)
If the operand is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression 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[.](#op-3.1.sentence-1)
The result has type âpointer to member of class C of type Tâ
and designates C::m[.](#op-3.1.sentence-2)
[*Note [3](#op-note-3)*:
A [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.1 General"))
and cannot be used to form a pointer to member[.](#op-3.1.sentence-3)
â *end note*]
- [(3.2)](#op-3.2)
Otherwise, the result has type âpointer to Tâ and points to
the designated object ([[intro.memory]](intro.memory "6.8.1 Memory model")) or function ([[basic.compound]](basic.compound "6.9.4 Compound types"))[.](#op-3.2.sentence-1)
If the operand designates an explicit object member function ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
the operand shall be
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]")[.](#op-3.2.sentence-2)
[*Note [4](#op-note-4)*:
In particular, taking the address of a variable of type âcv Tâ
yields a pointer of type âpointer to cv Tâ[.](#op-3.2.sentence-3)
â *end note*]
[*Example [1](#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](#op-note-5)*:
A pointer to member formed from a mutable non-static data
member ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers")) does not reflect the mutable specifier
associated with the non-static data member[.](#op-3.sentence-2)
â *end note*]
[4](#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.3 Qualified names [expr.prim.id.qual]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") not enclosed in parentheses[.](#op-4.sentence-1)
[*Note [6](#op-note-6)*:
That is, the expression &(qualified-id), where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") is enclosed in parentheses, does not form an
expression of type âpointer to memberâ[.](#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.3 Qualified 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.4 Function-to-pointer conversion"))[.](#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.2 Unqualified names [expr.prim.id.unqual]")'s class[.](#op-4.sentence-4)
â *end note*]
[5](#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[.](#op-5.sentence-1)
The operand of & shall not be a bit-field[.](#op-5.sentence-2)
[6](#op-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5315)
[*Note [7](#op-note-7)*:
The address of an overload set ([[over]](over "12 Overloading")) can be taken
only in a context that uniquely determines
which function is referred to (see [[over.over]](over.over "12.3 Address of an overload set"))[.](#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â[.](#op-6.sentence-2)
â *end note*]
[7](#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[.](#op-7.sentence-1)
Integral promotion is performed on integral or enumeration
operands[.](#op-7.sentence-2)
The type of the result is the type of the promoted operand[.](#op-7.sentence-3)
[8](#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[.](#op-8.sentence-1)
Integral
promotion is performed on integral or enumeration operands[.](#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[.](#op-8.sentence-3)
The type of the
result is the type of the promoted operand[.](#op-8.sentence-4)
[*Note [8](#op-note-8)*:
The result is the two's complement of the operand
(where operand and result are considered as unsigned)[.](#op-8.sentence-5)
â *end note*]
[9](#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.3 Standard conversions"));
its value is true if the converted operand is false and false otherwise[.](#op-9.sentence-1)
The type of the result is bool[.](#op-9.sentence-2)
[10](#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[.](#op-10.sentence-1)
Integral promotions are performed[.](#op-10.sentence-2)
The type of the result is the type of the promoted operand[.](#op-10.sentence-3)
Given the coefficients xi of the base-2 representation ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental 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[.](#op-10.sentence-4)
[*Note [9](#op-note-9)*:
The result is the ones' complement of the operand
(where operand and result are considered as unsigned)[.](#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.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")[.](#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.2 Unqualified names [expr.prim.id.unqual]") naming a destructor[.](#op-10.sentence-7)
[*Note [10](#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.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in a
member access expression or [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") is
unambiguously parsed as a destructor name[.](#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.4 Deprecated 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.19 Assignment 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.6 Increment 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.4 Coroutine 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.4 Await [expr.await]")
co_await [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.4 Await [expr.await]") shall appear only as a potentially-evaluated
expression within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") or [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
in either case
outside of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble"))[.](#expr.await-2.sentence-1)
In a [*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10 Declaration statement [stmt.dcl]") or in the[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") (if any)
of an [*init-statement*](stmt.pre#nt:init-statement "8.1 Preamble [stmt.pre]"), an [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall appear only in an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") of that[*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10 Declaration statement [stmt.dcl]") or [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]")[.](#expr.await-2.sentence-2)
An [*await-expression*](#nt:await-expression "7.6.2.4 Await [expr.await]") shall not appear in a
default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#expr.await-2.sentence-3)
An [*await-expression*](#nt:await-expression "7.6.2.4 Await [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.4 Await [expr.await]") shall not be
a potentially-evaluated subexpression
of the predicate of a contract assertion ([[basic.contract]](basic.contract "6.11 Contract assertions"))[.](#expr.await-2.sentence-5)
A context within a function where an [*await-expression*](#nt:await-expression "7.6.2.4 Await [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.4 Await [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.4 Coroutine 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.4 Await [expr.await]") was implicitly produced by
a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17 Yielding a value [expr.yield]") ([[expr.yield]](expr.yield "7.6.17 Yielding a value")),
an initial await expression,
or a final await expression ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
a search is performed for the name await_transform in the scope of P ([[class.member.lookup]](class.member.lookup "6.5.2 Member 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*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]"));
otherwise, *a* is the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.3 Operators in expressions")), and choosing the best one through
overload resolution ([[over.match]](over.match "12.2 Overload 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.5 Temporary 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
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 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.4 Await [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.4 Await [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,*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.4 Coroutine 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.2 Throwing 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.4 Coroutine definitions"))
without exiting any scopes ([[stmt.jump]](stmt.jump "8.8 Jump 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.4 Await [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.4 Await [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.4 Await [expr.await]") is indivisible ([[intro.execution]](intro.execution "6.10.1 Sequential 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 struct my_future {/* ... */bool await_ready(); void await_suspend(std::coroutine_handle<>);
T await_resume();};
template auto operator co_await(std::chrono::duration 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 h();
my_future 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.4 Await [expr.await]") outside of function suspension contextint a[] = { co_await h() }; // error: [*await-expression*](#nt:await-expression "7.6.2.4 Await [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.3 Context dependence [expr.context]"), or a parenthesized[*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.2 Fundamental 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.1 Memory model") for the definition of byte
and [[basic.types.general]](basic.types.general#term.object.representation "6.9.1 General") 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.2 Lvalue-to-rvalue conversion")),
array-to-pointer ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")), and
function-to-pointer ([[conv.func]](conv.func "7.3.4 Function-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.5 Temporary 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.11 Identifiers [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.4 Variadic templates"))[.](#expr.sizeof-4.sentence-2)
A sizeof... expression is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#expr.sizeof-4.sentence-3)
[*Example [1](#expr.sizeof-example-1)*: templatestruct 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.7 Constant expressions"))[.](#expr.sizeof-5.sentence-2)
The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::size_t is declared in the standard header[](cstddef.syn#header:%3ccstddef%3e "17.2.1 Header synopsis [cstddef.syn]") ([[cstddef.syn]](cstddef.syn "17.2.1 Header synopsis"), [[support.types.layout]](support.types.layout "17.2.4 Sizes, 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.2 Type 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.7 Constant expressions"))[.](#expr.alignof-2.sentence-2)
The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::size_t is declared in the standard header[](cstddef.syn#header:%3ccstddef%3e "17.2.1 Header synopsis [cstddef.syn]") ([[cstddef.syn]](cstddef.syn "17.2.1 Header synopsis"), [[support.types.layout]](support.types.layout "17.2.4 Sizes, 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](#noexcept) noexcept operator [[expr.unary.noexcept]](expr.unary.noexcept)
[noexcept-expression:](#nt:noexcept-expression "7.6.2.7 noexcept operator [expr.unary.noexcept]")
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
[1](#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.3 Context dependence"))[.](#noexcept-1.sentence-1)
If the operand is a prvalue,
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) is applied[.](#noexcept-1.sentence-2)
[2](#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[.](#noexcept-2.sentence-1)
The result is false if
the full-expression of the operand is potentially-throwing ([[except.spec]](except.spec "14.5 Exception specifications")), andtrue otherwise[.](#noexcept-2.sentence-2)
[*Note [1](#noexcept-note-1)*:
A [*noexcept-expression*](#nt:noexcept-expression "7.6.2.7 noexcept operator [expr.unary.noexcept]") is an integral constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#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.8 New [expr.new]") attempts to create an object of the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") ([[dcl.name]](dcl.name "9.3.2 Type 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.8 New [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.1 General")),
but not an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract classes")) or array
thereof ([[intro.object]](intro.object "6.8.2 Object 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.8 New [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.2 Type 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.8 New [expr.new]") has a cv-qualified type[.](#expr.new-1.sentence-5)
â *end note*]
[new-expression:](#nt:new-expression "7.6.2.8 New [expr.new]")
::opt new [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]")opt [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]")opt
::opt new [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]")opt
[new-placement:](#nt:new-placement "7.6.2.8 New [expr.new]")
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )
[new-type-id:](#nt:new-type-id "7.6.2.8 New [expr.new]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8 New [expr.new]")opt
[new-declarator:](#nt:new-declarator "7.6.2.8 New [expr.new]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8 New [expr.new]")opt
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]")
[noptr-new-declarator:](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]")
[ [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
[new-initializer:](#nt:new-initializer "7.6.2.8 New [expr.new]")
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [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.7 Placeholder type specifiers [dcl.spec.auto]") or
a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types"))
appears in the[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") of a [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]"),
the allocated type is deduced as follows:
Let*init* be the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]"), if any,
andT be the [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of
the [*new-expression*](#nt:new-expression "7.6.2.8 New [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.7 Placeholder 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 struct A { A(T, T); };auto y = new A{1, 2}; // allocated type is A â *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.8 New [expr.new]") in a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") is the longest
possible sequence of [*new-declarator*](#nt:new-declarator "7.6.2.8 New [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.8 New [expr.new]") of a [*new-expression*](#nt:new-expression "7.6.2.8 New [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.4 Compound 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [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.7 Constant expressions [expr.const]") in a[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") shall be a converted constant
expression ([[expr.const]](expr.const "7.7 Constant 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*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [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*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [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.7 Constant expressions [expr.const]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [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.2 Type names [dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") denotes an array type of unknown bound ([[dcl.array]](dcl.array "9.3.4.5 Arrays")),
the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [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.8 New [expr.new]") ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"), [[dcl.init.string]](dcl.init.string "9.5.3 Character arrays"))[.](#expr.new-7.sentence-1)
[8](#expr.new-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5917)
If the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") is present, it is implicitly converted to std::size_t[.](#expr.new-8.sentence-1)
The value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.3 User-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.8 New [expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [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.5 String literals [lex.string]") ([[lex.string]](lex.string "5.13.5 String literals"))) exceeds the
number of elements to initialize[.](#expr.new-8.sentence-2)
If the value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is invalid after converting to std::size_t:
- [(8.5)](#expr.new-8.5)
if the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.5 Exception specifications")),
the value of the [*new-expression*](#nt:new-expression "7.6.2.8 New [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.8 New [expr.new]") terminates by throwing an
exception of a type that would match a handler ([[except.handle]](except.handle "14.4 Handling an exception")) of type[std::bad_array_new_length](new.badlength "17.6.4.2 Class bad_array_new_length [new.badlength]")[.](#expr.new-8.sentence-3)
When the value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.8 New [expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"), and
the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.5 List-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.1 General [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.8 New [expr.new]") have dynamic storage
duration ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5 Dynamic 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.8 New [expr.new]") syntax is used or the[*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") denotes an array type),
the [*new-expression*](#nt:new-expression "7.6.2.8 New [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.8 New [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.8 New [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.2 Allocation functions"))[.](#expr.new-12.sentence-1)
If
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") terminates by throwing an exception, it
may release storage by calling a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation 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.5 Dynamic storage duration"), [[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#expr.new-12.sentence-5)
A C++ program can provide alternative definitions of
these functions ([[replacement.functions]](replacement.functions "16.4.5.6 Replacement functions")) and/or class-specific
versions ([[class.free]](class.free "11.4.11 Allocation 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.8 New [expr.new]") can include functions that do not perform allocation or deallocation;
for example, see [[new.delete.placement]](new.delete.placement "17.6.3.4 Non-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.8 New [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.2 Member 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.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array 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.8 New [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.7 Constant 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.8 New [expr.new]") e1 to provide
storage for a [*new-expression*](#nt:new-expression "7.6.2.8 New [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.9 Delete [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.9 Delete [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 a{new (std::nothrow) char[8]};
std::unique_ptr b{new (std::nothrow) char[8]};
std::unique_ptr c{new (std::nothrow) char[x]};
g(a.get(), b.get(), c.get());}void cannot_merge(int x) { std::unique_ptr a{new char[8]}; try {// Merging this allocation would change its catch handler. std::unique_ptr 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.8 New [expr.new]") calls an allocation function and that
allocation has not been extended, the[*new-expression*](#nt:new-expression "7.6.2.8 New [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.4 Non-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.8 New [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.3 Alignment [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.8 New [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.8 New [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.8 New [expr.new]")*[*new-expression*](#nt:new-expression "7.6.2.8 New [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.8 New [expr.new]") syntax is used,
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* in its [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [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.8 New [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.8 New [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.5 Exception 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.2 Allocation functions"), [[except]](except "14 Exception handling"), [[bad.alloc]](bad.alloc "17.6.4.1 Class 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.4 Non-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.8 New [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.3 Alignment"))
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.8 New [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.8 New [expr.new]") is omitted, the object is
default-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.8 New [expr.new]") is interpreted according to
the initialization rules of [[dcl.init]](dcl.init "9.5 Initializers") 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.8 New [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.8 New [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.8 New [expr.new]") creates an array of objects of class type, the destructor is potentially
invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#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.8 New [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.8 New [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.6 Functions")), 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.9 Delete"))[.](#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.8 New [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.8 New [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.8 New [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.8 New [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.9 Delete [expr.delete]") operator destroys a[most derived object](intro.object#def:most_derived_object "6.8.2 Object model [intro.object]") or array created by a[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")[.](#expr.delete-1.sentence-1)
[delete-expression:](#nt:delete-expression "7.6.2.9 Delete [expr.delete]")
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
The first alternative is a[*single-object delete expression*](#def:delete,single-object "7.6.2.9 Delete [expr.delete]"), and the
second is an [*array delete expression*](#def:delete,array "7.6.2.9 Delete [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.3 Standard 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.9 Delete [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.8 New [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.8 New [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.8 New [expr.new]") whose
allocation function was not a non-allocating form ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-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.9 Delete [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.8 New [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.9 Delete [expr.delete]"); it is not necessary to cast away the
constness ([[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")) of the pointer expression before it is
used as the operand of the [*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [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.6 Qualification 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.9 Delete [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.9 Delete [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.9 Delete [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.3 Initializing 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.9 Delete [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.8 New [expr.new]") for the object to
be deleted was not omitted and the allocation was not extended ([[expr.new]](#expr.new "7.6.2.8 New")), the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") shall call a [deallocation
function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation 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.8 New [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.8 New [expr.new]"), and the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [expr.delete]") for every other pointer value produced by a[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") that had storage provided by the extended[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") has been evaluated, the[*delete-expression*](#nt:delete-expression "7.6.2.9 Delete [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.8 New [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.9 Delete [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.9 Delete [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.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#expr.delete-7.sentence-2)
A C++ program can provide alternative definitions of these
functions ([[replacement.functions]](replacement.functions "16.4.5.6 Replacement functions")), and/or class-specific
versions ([[class.free]](class.free "11.4.11 Allocation 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.9 Delete [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.7 Destructors"))[.](#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.3 Deallocation 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.5 Name 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.9 Delete [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.9 Delete [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.8 New")) 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.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array 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.1 General [expr.prim.lambda.general]") with a [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1 General [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.1 General [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.8 New [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.10 The reflection operator [expr.reflect]")
^^ ::
^^ [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]")
^^ [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")
^^ [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")
[reflection-name:](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.10 The reflection operator [expr.reflect]"),
yields a prvalue of type std::meta::info ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental 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.10 The 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.10 The reflection operator [expr.reflect]") are those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) and
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#expr.reflect-2.sentence-1)
The terminal name of a [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.10 The 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.10 The reflection operator [expr.reflect]")[.](#expr.reflect-3.sentence-1)
An unparenthesized [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The 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 struct X {};consteval bool operator<(std::meta::info, X) { return false; }consteval void g(std::meta::info r, X xv) { r == ^^int && true; // error: ^^ applies to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.2 Type names [dcl.name]")^^X < xv; // error: [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") that represents a template is followed by <(^^X) < xv; // OK^^X < 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.10 The 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.10 The reflection operator [expr.reflect]") R matches
the form ^^[*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"),
it is interpreted as such;
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.10 The using declaration [namespace.udecl]") during a single search ([[basic.lookup.general]](basic.lookup.general "6.5.1 General"), [[namespace.udecl]](namespace.udecl "9.10 The 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.10 The 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.2 Member name lookup")constexpr std::meta::info r2 = ^^D::S; // OK, result C::S not found through [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The 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.3 Namespace 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.1 General [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.9 Namespaces")),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.9 Concept 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.3 Names 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.1 Preamble")), then:
+
[(5.5.1.1)](#expr.reflect-5.5.1.1)
If the [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") is of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.3 Simple 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.2 Anonymous 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.10 The reflection operator [expr.reflect]") shall be an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.10 The reflection operator [expr.reflect]") R of the form^^[*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.2 Type names [dcl.name]") designates
a placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1 General")),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.2 Type names [dcl.name]") names a type alias
that is a specialization of an alias template ([[temp.alias]](temp.alias "13.7.8 Alias 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.2 Type 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.10 The reflection operator [expr.reflect]") R of the form^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.1 General [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.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")),
* [(7.1.2)](#expr.reflect-7.1.2)
a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")),
* [(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.1 General [expr.prim.req.general]") ([[expr.prim.req]](expr.prim.req "7.5.8 Requires expressions")), or
* [(7.1.4)](#expr.reflect-7.1.4)
a local entity E ([[basic.pre]](basic.pre "6.1 Preamble")) 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.1 General [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.3 Address 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.1 General [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.2 Unqualified 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.4 Pack 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.1 General [expr.prim.id.general]") of
a [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context dependence"))[.](#expr.reflect-7.sentence-2)
[*Example [3](#expr.reflect-example-3)*: template void fn() requires (^^T != ^^int);template void fn() requires (^^T == ^^int);template void fn() requires (sizeof(T) == sizeof(int));
constexpr std::meta::info a = ^^fn; // OKconstexpr std::meta::info b = ^^fn; // error: ambiguousconstexpr std::meta::info c = ^^std::vector; // OKtemplatestruct S {static constexpr std::meta::info r = ^^T; using type = T;};static_assert(S::r == ^^int);static_assert(^^S::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.1 General")) â *end example*]