[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*]