[expr.post]

# 7 Expressions [[expr]](./#expr)

## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.post)

### 7.6.1 Postfix expressions [expr.post]

#### [7.6.1.1](#general) General [[expr.post.general]](expr.post.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3658)

Postfix expressions group left-to-right[.](#general-1.sentence-1)

[postfix-expression:](#nt:postfix-expression "7.6.1.1 General [expr.post.general]")  
[*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1 Grammar [expr.prim.grammar]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") [ [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]")opt ]  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") ( [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )  
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )  
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )  
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")  
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") . templateopt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") . [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") -> templateopt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") -> [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]")  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") ++  
[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") --  
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )  
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )  
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )  
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )  
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )  
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )

[expression-list:](#nt:expression-list "7.6.1.1 General [expr.post.general]")  
[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]")

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3689)

[*Note [1](#general-note-1)*:

The > token following the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") in a dynamic_cast,static_cast, reinterpret_cast, orconst_cast can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3 Names of template specializations"))[.](#general-2.sentence-1)

â *end note*]

#### [7.6.1.2](#expr.sub) Subscripting [[expr.sub]](expr.sub)

[1](#expr.sub-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3701)

A [*subscript expression*](#def:expression,subscript "7.6.1.2 Subscripting [expr.sub]") is a postfix expression
followed by square brackets containing
a possibly empty, comma-separated list of [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* that constitute the arguments to the subscript operator[.](#expr.sub-1.sentence-1)

The [*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") and
the initialization of the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of
any applicable subscript operator function ([[over.sub]](over.sub "12.4.5 Subscripting")) is sequenced before
each expression in the [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]") and also before
any default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#expr.sub-1.sentence-2)

The initialization of a non-object parameter of
a subscript operator function S,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of
any other non-object parameter of S[.](#expr.sub-1.sentence-3)

[2](#expr.sub-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3719)

With the built-in subscript operator,
an [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be present,
consisting of a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")[.](#expr.sub-2.sentence-1)

One of the expressions shall be a glvalue of type âarray ofTâ or a prvalue of type âpointer
to Tâ and the other shall be a prvalue of unscoped enumeration or integral type[.](#expr.sub-2.sentence-2)

The result is of type âTâ[.](#expr.sub-2.sentence-3)

The type âTâ shall be a completely-defined object type[.](#expr.sub-2.sentence-4)[48](#footnote-48 "This is true even if the subscript operator is used in the following common idiom: &amp;x[0].")

The expression E1[E2] is identical (by definition) to*((E1)+(E2)),
except that in the case of an array operand, the result is an lvalue
if that operand is an lvalue and an xvalue otherwise[.](#expr.sub-2.sentence-5)

[3](#expr.sub-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3739)

[*Note [1](#expr.sub-note-1)*:

Despite its asymmetric appearance, subscripting is a commutative
operation except for sequencing[.](#expr.sub-3.sentence-1)

See [[expr.unary]](expr.unary "7.6.2 Unary expressions") and [[expr.add]](expr.add "7.6.6 Additive operators") for details of * and+ and [[dcl.array]](dcl.array "9.3.4.5 Arrays") for details of array types[.](#expr.sub-3.sentence-2)

â *end note*]

[48)](#footnote-48)[48)](#footnoteref-48)

This
is true even if the subscript operator is used in the following common idiom:&x[0][.](#footnote-48.sentence-1)

#### [7.6.1.3](#expr.call) Function call [[expr.call]](expr.call)

[1](#expr.call-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3749)

A function call is a postfix expression followed by parentheses
containing a possibly empty, comma-separated list of[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* which
constitute the arguments to the function[.](#expr.call-1.sentence-1)

[*Note [1](#expr.call-note-1)*:

If the postfix expression is a function or member function name,
the appropriate function and the validity of the call
are determined according to the rules in [[over.match]](over.match "12.2 Overload resolution")[.](#expr.call-1.sentence-2)

â *end note*]

The postfix expression shall
have function type or function pointer type[.](#expr.call-1.sentence-3)

For a call to a non-member function or to a static member function,
the postfix expression shall be either an lvalue that refers to a
function (in which case the function-to-pointer standard
conversion ([[conv.func]](conv.func "7.3.4 Function-to-pointer conversion")) is suppressed on the postfix expression),
or a prvalue of function pointer type[.](#expr.call-1.sentence-4)

[2](#expr.call-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3770)

If the selected
function is non-virtual, or if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") in the class
member access expression is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]"), that function is
called[.](#expr.call-2.sentence-1)

Otherwise, its [final overrider](class.virtual#def:final_overrider "11.7.3 Virtual functions [class.virtual]") in the dynamic type
of the object expression is called; such a call is referred to as a[*virtual function call*](#def:function,virtual_function_call "7.6.1.3 Function call [expr.call]")[.](#expr.call-2.sentence-2)

[*Note [2](#expr.call-note-2)*:

The dynamic type is the type of the object referred to by the
current value of the object expression[.](#expr.call-2.sentence-3)

[[class.cdtor]](class.cdtor "11.9.5 Construction and destruction") describes the
behavior of virtual function calls when the object expression
refers to
an object under construction or destruction[.](#expr.call-2.sentence-4)

â *end note*]

[3](#expr.call-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3785)

[*Note [3](#expr.call-note-3)*:

If a function or member function name is used, and [name
lookup](basic.lookup "6.5 Name lookup [basic.lookup]") does not find a declaration of that name,
the program is ill-formed[.](#expr.call-3.sentence-1)

No function is implicitly declared by such a
call[.](#expr.call-3.sentence-2)

â *end note*]

[4](#expr.call-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3793)

If the [*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") names
a destructor or pseudo-destructor ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5 Destruction")),
the type of the function call expression is void; otherwise, the
type of the function call expression is the return type of the
statically chosen function (i.e., ignoring the virtual keyword),
even if the type of the function actually called is different[.](#expr.call-4.sentence-1)

If the [*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") names a pseudo-destructor
(in which case the [*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") is a possibly-parenthesized class member access),
the function call destroys
the object of scalar type
denoted by the object expression
of the class member access ([[expr.ref]](#expr.ref "7.6.1.5 Class member access"), [[basic.life]](basic.life "6.8.4 Lifetime"))[.](#expr.call-4.sentence-2)

[5](#expr.call-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3809)

A type Tcall is[*call-compatible*](#def:call-compatible "7.6.1.3 Function call [expr.call]") with a function type Tfunc if Tcall is the same type as Tfunc or
if the type âpointer to Tfuncâ can be
converted to type âpointer to Tcallâ
via a function pointer conversion ([[conv.fctptr]](conv.fctptr "7.3.14 Function pointer conversions"))[.](#expr.call-5.sentence-1)

Calling a function through an
expression whose function type
is not call-compatible with the
type of the called function's
definition results in undefined behavior[.](#expr.call-5.sentence-2)

[*Note [4](#expr.call-note-4)*:

This requirement allows the case
when the expression has the type of a
potentially-throwing function, but the called function has
a non-throwing exception specification,
and the function types are otherwise the same[.](#expr.call-5.sentence-3)

â *end note*]

[6](#expr.call-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3829)

When a function is called, each parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) is
initialized ([[dcl.init]](dcl.init "9.5 Initializers"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")) with
its corresponding argument,
and each precondition assertion of the function
is evaluated ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))[.](#expr.call-6.sentence-1)

If the function is an explicit object member function and
there is an implied object argument ([[over.call.func]](over.call.func "12.2.2.2.2 Call to designated function")),
the list of provided arguments is preceded by the implied object argument
for the purposes of this correspondence[.](#expr.call-6.sentence-2)

If there is no corresponding argument,
the default argument for the parameter is used[.](#expr.call-6.sentence-3)

[*Example [1](#expr.call-example-1)*: template<typename ...T> int f(int n = 0, T ...t);int x = f<int>(); // error: no argument for second function parameter â *end example*]

If the function is an implicit object member
function,
the object expression of the class member access shall be a glvalue and
the implicit object parameter of the function ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists"))
is initialized with that glvalue,
converted as if by an [explicit type conversion](expr.cast "7.6.3 Explicit type conversion (cast notation) [expr.cast]")[.](#expr.call-6.sentence-4)

[*Note [5](#expr.call-note-5)*:

There is no access or ambiguity checking on this conversion; the access
checking and disambiguation are done as part of the (possibly implicit)
class member access operator[.](#expr.call-6.sentence-5)

See [[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"), [[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members"),
and [[expr.ref]](#expr.ref "7.6.1.5 Class member access")[.](#expr.call-6.sentence-6)

â *end note*]

When a function is called, the type of any parameter
shall not be a class type that is either incomplete or abstract[.](#expr.call-6.sentence-7)

[*Note [6](#expr.call-note-6)*:

This still allows a parameter to be a pointer or reference to such
a type[.](#expr.call-6.sentence-8)

However, it prevents a passed-by-value parameter
to have an incomplete or abstract class type[.](#expr.call-6.sentence-9)

â *end note*]

It is implementation-defined
whether a parameter is destroyed
when the function in which it is defined exits ([[stmt.return]](stmt.return "8.8.4 The return statement"), [[except.ctor]](except.ctor "14.3 Stack unwinding"), [[expr.await]](expr.await "7.6.2.4 Await"))
or at the end of the enclosing full-expression;
parameters are always destroyed in the reverse order of their construction[.](#expr.call-6.sentence-10)

The initialization and destruction of each parameter occurs
within the context of the full-expression ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))
where the function call appears[.](#expr.call-6.sentence-11)

[*Example [2](#expr.call-example-2)*:

The access ([[class.access.general]](class.access.general "11.8.1 General")) of the
constructor, conversion functions, or destructor is
checked at the point of call[.](#expr.call-6.sentence-12)

If a constructor
or destructor for a function parameter throws an exception,
any [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble"))
of the called function
with a handler that can handle the exception
is not considered[.](#expr.call-6.sentence-13)

â *end example*]

[7](#expr.call-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3890)

The [*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]") is sequenced before
each [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in the [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]") and any default argument[.](#expr.call-7.sentence-1)

The initialization of a parameter or,
if the implementation introduces any temporary objects
to hold the values of function parameters ([[class.temporary]](class.temporary "6.8.7 Temporary objects")),
the initialization of those temporaries,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of any other parameter[.](#expr.call-7.sentence-2)

These evaluations are
sequenced before
the evaluation of the precondition assertions of the function,
which are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))[.](#expr.call-7.sentence-3)

For any temporaries
introduced to hold the values of function parameters,
the initialization of the parameter objects from those temporaries
is indeterminately sequenced with respect to
the evaluation of each precondition assertion[.](#expr.call-7.sentence-4)

[*Note [7](#expr.call-note-7)*:

All side effects of
argument evaluations are sequenced before the function is
entered (see [[intro.execution]](intro.execution "6.10.1 Sequential execution"))[.](#expr.call-7.sentence-5)

â *end note*]

[*Example [3](#expr.call-example-3)*: void f() { std::string s = "but I have heard it works even if you don't believe in it";
 s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
 assert(s == "I have heard it works only if you believe in it"); // OK} â *end example*]

[*Note [8](#expr.call-note-8)*:

If an operator function is invoked
using operator notation,
argument evaluation is sequenced
as specified for the built-in operator;
see [[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions")[.](#expr.call-7.sentence-6)

â *end note*]

[*Example [4](#expr.call-example-4)*: struct S { S(int);};int operator<<(S, int);int i, j;int x = S(i=1) << (i=2);int y = operator<<(S(j=1), j=2);

After performing the initializations,
the value of i is 2 (see [[expr.shift]](expr.shift "7.6.7 Shift operators")),
but it is unspecified whether the value of j is 1 or 2[.](#expr.call-7.sentence-7)

â *end example*]

[8](#expr.call-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3948)

The result of a function call is the result of the possibly-converted operand
of the return statement ([[stmt.return]](stmt.return "8.8.4 The return statement"))
that transferred control out of the called function (if any),
except in a virtual function call if the return type of the
final overrider is different from the return type of the statically
chosen function, the value returned from the final overrider is
converted to the return type of the statically chosen function[.](#expr.call-8.sentence-1)

[9](#expr.call-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3957)

When the called function exits normally ([[stmt.return]](stmt.return "8.8.4 The return statement"), [[expr.await]](expr.await "7.6.2.4 Await")),
all postcondition assertions of the function
are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))[.](#expr.call-9.sentence-1)

If the implementation introduces any temporary objects
to hold the result value as specified in [[class.temporary]](class.temporary "6.8.7 Temporary objects"),
the evaluation of each postcondition assertion
is indeterminately sequenced with respect to
the initialization of any of those temporaries or the result object[.](#expr.call-9.sentence-2)

These evaluations, in turn, are sequenced before
the destruction of any function parameters[.](#expr.call-9.sentence-3)

[10](#expr.call-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3969)

[*Note [9](#expr.call-note-9)*:

A function can change the values of its non-const parameters, but these
changes cannot affect the values of the arguments except where a
parameter is of a reference type ([[dcl.ref]](dcl.ref "9.3.4.3 References")); if the reference is to
a const-qualified type, const_cast needs to be used to
cast away the constness in order to modify the argument's value[.](#expr.call-10.sentence-1)

Where a
parameter is of const reference type a temporary object is
introduced if
needed ([[dcl.type]](dcl.type "9.2.9 Type specifiers"), [[lex.literal]](lex.literal "5.13 Literals"), [[lex.string]](lex.string "5.13.5 String literals"), [[dcl.array]](dcl.array "9.3.4.5 Arrays"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#expr.call-10.sentence-2)

In addition, it is possible to modify the values of non-constant objects through
pointer parameters[.](#expr.call-10.sentence-3)

â *end note*]

[11](#expr.call-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3989)

A function can be declared to accept fewer arguments (by declaring [default
arguments](dcl.fct.default "9.3.4.7 Default arguments [dcl.fct.default]")) or more arguments (by using the ellipsis,..., or a function parameter pack ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))) than the number of
parameters in the [function definition](dcl.fct.def "9.6 Function definitions [dcl.fct.def]")[.](#expr.call-11.sentence-1)

[*Note [10](#expr.call-note-10)*:

This implies that, except where the ellipsis (...) or a function
parameter pack is used, a parameter is available for each argument[.](#expr.call-11.sentence-2)

â *end note*]

[12](#expr.call-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4001)

When there is no parameter for a given argument, the argument is passed
in such a way that the receiving function can obtain the value of the
argument by invoking va_arg ([[support.runtime]](support.runtime "17.14 Other runtime support"))[.](#expr.call-12.sentence-1)

[*Note [11](#expr.call-note-11)*:

This paragraph does not apply to arguments passed to a function parameter pack[.](#expr.call-12.sentence-2)

Function parameter packs are expanded during template instantiation ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")),
thus each such argument has a corresponding parameter when a function template
specialization is actually called[.](#expr.call-12.sentence-3)

â *end note*]

The[lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") standard conversions are
performed on the argument expression[.](#expr.call-12.sentence-4)

An argument that has type cv std​::​nullptr_t is converted
to type void* ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"))[.](#expr.call-12.sentence-5)

After these conversions, if the
argument does not have arithmetic, enumeration, pointer, pointer-to-member,
or class type, the program is ill-formed[.](#expr.call-12.sentence-6)

Passing a potentially-evaluated argument
of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) or
of a class type ([[class]](class "11 Classes")) having
an eligible non-trivial copy constructor ([[special]](special "11.4.4 Special member functions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")),
an eligible non-trivial move constructor, or
a non-trivial destructor ([[class.dtor]](class.dtor "11.4.7 Destructors")),
with no corresponding parameter, is conditionally-supported withimplementation-defined semantics[.](#expr.call-12.sentence-7)

If the argument has
integral or enumeration type that is subject to the [integral
promotions](conv.prom "7.3.7 Integral promotions [conv.prom]"), or a floating-point type that is subject to the[floating-point promotion](conv.fpprom "7.3.8 Floating-point promotion [conv.fpprom]"), the value of the argument is converted to the
promoted type before the call[.](#expr.call-12.sentence-8)

These promotions are referred to as
the [*default argument promotions*](#def:promotion,default_argument_promotion "7.6.1.3 Function call [expr.call]")[.](#expr.call-12.sentence-9)

[13](#expr.call-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4035)

Recursive calls are permitted, except to the [main function](basic.start.main "6.10.3.1 main function [basic.start.main]")[.](#expr.call-13.sentence-1)

[14](#expr.call-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4040)

A function call is an lvalue
if the result type is an lvalue reference type or an rvalue reference to function type,
an xvalue if the result type is an rvalue reference to object type, and a prvalue
otherwise[.](#expr.call-14.sentence-1)

If it is a non-void prvalue,
the type of the function call expression shall be complete,
except as specified in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")[.](#expr.call-14.sentence-2)

#### [7.6.1.4](#expr.type.conv) Explicit type conversion (functional notation) [[expr.type.conv]](expr.type.conv)

[1](#expr.type.conv-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4051)

A [](dcl.type.simple "9.2.9.3 Simple type specifiers [dcl.type.simple]")[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") or[](temp.res "13.8 Name resolution [temp.res]")[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") followed
by a parenthesized optional [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]") or
by a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") (the initializer)
constructs a value of the specified type
given the initializer[.](#expr.type.conv-1.sentence-1)

If the type is a placeholder
for a deduced class type,
it is replaced by the return type
of the function selected by overload resolution
for [class template deduction](over.match.class.deduct "12.2.2.9 Class template argument deduction [over.match.class.deduct]") for the remainder of this subclause[.](#expr.type.conv-1.sentence-2)

Otherwise, if the type contains a placeholder type,
it is replaced by the type
determined by placeholder type deduction ([[dcl.type.auto.deduct]](dcl.type.auto.deduct "9.2.9.7.2 Placeholder type deduction"))[.](#expr.type.conv-1.sentence-3)

Let T denote the resulting type[.](#expr.type.conv-1.sentence-4)

Then:

- [(1.1)](#expr.type.conv-1.1)

  If the initializer is a parenthesized single expression,
the type conversion expression is equivalent
to the corresponding cast
expression ([[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))[.](#expr.type.conv-1.1.sentence-1)

- [(1.2)](#expr.type.conv-1.2)

  Otherwise, if T is cv void,
the initializer shall be () or {} (after pack expansion, if any), and
the expression is a prvalue of type void that performs no initialization[.](#expr.type.conv-1.2.sentence-1)

- [(1.3)](#expr.type.conv-1.3)

  Otherwise, if T is a reference type,
the expression has the same effect as
direct-initializing an invented variable t of type T from
the initializer and then
using t as the result of the expression;
the result is an lvalue ifT is an lvalue reference type or
an rvalue reference to function type and
an xvalue otherwise[.](#expr.type.conv-1.3.sentence-1)

- [(1.4)](#expr.type.conv-1.4)

  Otherwise,
the expression is a prvalue of type T whose result object is direct-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))
with the initializer[.](#expr.type.conv-1.4.sentence-1)

If the initializer is a parenthesized optional [*expression-list*](#nt:expression-list "7.6.1.1 General [expr.post.general]"),T shall not be an array type[.](#expr.type.conv-1.sentence-6)

[*Example [1](#expr.type.conv-example-1)*: struct A {};void f(A&); // #1void f(A&&); // #2 A& g();void h() { f(g()); // calls #1 f(A(g())); // calls #2 with a temporary object f(auto(g())); // calls #2 with a temporary object} â *end example*]

#### [7.6.1.5](#expr.ref) Class member access [[expr.ref]](expr.ref)

[1](#expr.ref-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4128)

A postfix expression followed by a dot . or an arrow ->,
optionally followed by the keywordtemplate, and then followed by an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
is a postfix expression[.](#expr.ref-1.sentence-1)

[*Note [1](#expr.ref-note-1)*:

If the keyword template is used and
followed by an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"),
the unqualified name
is considered to refer to a template ([[temp.names]](temp.names "13.3 Names of template specializations"))[.](#expr.ref-1.sentence-2)

If a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") results and is followed by a ​::​,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#expr.ref-1.sentence-3)

â *end note*]

[2](#expr.ref-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4153)

For a dot that is followed by an expression
that designates a static member or an enumerator,
the first expression is a discarded-value expression ([[expr.context]](expr.context "7.2.3 Context dependence"));
if the expression after the dot designates a non-static data member,
the first expression shall be a glvalue[.](#expr.ref-2.sentence-1)

A postfix expression that is followed by an arrow
shall be a prvalue having pointer type[.](#expr.ref-2.sentence-2)

The expression E1->E2 is
converted to the equivalent form (*(E1)).E2; the remainder of[[expr.ref]](#expr.ref "7.6.1.5 Class member access") will address only the form using a dot[.](#expr.ref-2.sentence-3)[49](#footnote-49 "Note that (*(E1)) is an lvalue.")

[3](#expr.ref-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4170)

The postfix expression before the dot is evaluated;[50](#footnote-50 "If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.") the result of that evaluation,
together with
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
determines the result of the entire postfix expression[.](#expr.ref-3.sentence-1)

[4](#expr.ref-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4184)

Abbreviating[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]").[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or[*postfix-expression*](#nt:postfix-expression "7.6.1.1 General [expr.post.general]").[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") as E1.E2, E1 is called the [*object expression*](expr.mptr.oper#def:object_expression "7.6.4 Pointer-to-member operators [expr.mptr.oper]")[.](#expr.ref-4.sentence-1)

If the object expression is of scalar type,E2 shall name the pseudo-destructor
of that same type (ignoring cv-qualifications) andE1.E2 is a prvalue of type âfunction of () returning voidâ[.](#expr.ref-4.sentence-2)

[*Note [2](#expr.ref-note-2)*:

This value can only be used
for a notional function call ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5 Destruction"))[.](#expr.ref-4.sentence-3)

â *end note*]

[5](#expr.ref-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4198)

Otherwise, the object expression shall be of class type[.](#expr.ref-5.sentence-1)

The class type shall be complete
unless the class member access appears in the definition of that class[.](#expr.ref-5.sentence-2)

[*Note [3](#expr.ref-note-3)*:

The program is ill-formed if the result differs from that
when the class is complete ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#expr.ref-5.sentence-3)

â *end note*]

[*Note [4](#expr.ref-note-4)*:

[[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup") describes how names are looked up after the. and -> operators[.](#expr.ref-5.sentence-4)

â *end note*]

[6](#expr.ref-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4211)

If E2 is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]"),
then let T1 be the type of E1[.](#expr.ref-6.sentence-1)

E2 shall designate either
a member of T1 or
a direct base class relationship (T1, B)[.](#expr.ref-6.sentence-2)

[7](#expr.ref-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4218)

If E2 designates a bit-field, E1.E2 is a bit-field[.](#expr.ref-7.sentence-1)

The
type and value category of E1.E2 are determined as follows[.](#expr.ref-7.sentence-2)

In the remainder of [[expr.ref]](#expr.ref "7.6.1.5 Class member access"), *cq* represents eitherconst or the absence of const and *vq* represents
either volatile or the absence of volatile[.](#expr.ref-7.sentence-3)

*cv* represents an arbitrary set of cv-qualifiers, as defined
in [[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")[.](#expr.ref-7.sentence-4)

[8](#expr.ref-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4227)

If E2 designates an entity
that is declared to have type âreference to Tâ, thenE1.E2 is an lvalue of type T[.](#expr.ref-8.sentence-1)

In that case, if E2 designates a static data member,E1.E2 designates the object or function to which
the reference is bound,
otherwise E1.E2 designates the object or function to which
the corresponding reference member of E1 is bound[.](#expr.ref-8.sentence-2)

Otherwise, one of the following rules applies[.](#expr.ref-8.sentence-3)

- [(8.1)](#expr.ref-8.1)

  If E2 designates a static data member and the type of E2 is T, then E1.E2 is an lvalue; the expression designates
the named member of the class[.](#expr.ref-8.1.sentence-1)
  The type of E1.E2 is T[.](#expr.ref-8.1.sentence-2)

- [(8.2)](#expr.ref-8.2)

  Otherwise, if E2 designates a non-static data member and the type ofE1 is â*cq1 vq1* Xâ, and the type of E2 is â*cq2 vq2* Tâ, the expression designates the corresponding
member subobject of the object designated by E1[.](#expr.ref-8.2.sentence-1)
  If E1 is an lvalue, then E1.E2 is an lvalue;
otherwise E1.E2 is an xvalue[.](#expr.ref-8.2.sentence-2)
  Let the notation *vq12* stand for the âunionâ of*vq1* and *vq2*; that is, if *vq1* or *vq2* is volatile, then *vq12* is volatile[.](#expr.ref-8.2.sentence-3)
  Similarly,
let the notation *cq12* stand for the âunionâ of *cq1* and *cq2*; that is, if *cq1* or *cq2* isconst, then *cq12* is const[.](#expr.ref-8.2.sentence-4)
  If the entity designated by E2 is declared to be a mutable member,
then the type of E1.E2 is â*vq12* Tâ[.](#expr.ref-8.2.sentence-5)
  If the entity designated by E2 is not declared to be a mutable member,
then the type of E1.E2 is â*cq12* *vq12* Tâ[.](#expr.ref-8.2.sentence-6)

- [(8.3)](#expr.ref-8.3)

  Otherwise, if E2 denotes an overload set,
the expression shall be the (possibly-parenthesized) left-hand operand of
a member function call ([[expr.call]](#expr.call "7.6.1.3 Function call")), and
function overload resolution ([[over.match]](over.match "12.2 Overload resolution"))
is used to select the function to which E2 refers[.](#expr.ref-8.3.sentence-1)
  The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2[.](#expr.ref-8.3.sentence-2)

  * [(8.3.1)](#expr.ref-8.3.1)

      If E2 refers to a static member function,E1.E2 is an lvalue[.](#expr.ref-8.3.1.sentence-1)

  * [(8.3.2)](#expr.ref-8.3.2)

      Otherwise (when E2 refers to a non-static member function),E1.E2 is a prvalue[.](#expr.ref-8.3.2.sentence-1)
      [*Note [5](#expr.ref-note-5)*:
      Any redundant set of parentheses surrounding the expression
is ignored ([[expr.prim.paren]](expr.prim.paren "7.5.4 Parentheses"))[.](#expr.ref-8.3.2.sentence-2)
 â *end note*]

- [(8.4)](#expr.ref-8.4)

  Otherwise, if E2 designates a nested type,
the expression E1.E2 is ill-formed[.](#expr.ref-8.4.sentence-1)

- [(8.5)](#expr.ref-8.5)

  Otherwise, if E2 designates a member enumerator and the type of E2 is T, the expression E1.E2 is a prvalue of type T whose value is the value of the enumerator[.](#expr.ref-8.5.sentence-1)

- [(8.6)](#expr.ref-8.6)

  Otherwise, if E2 designates a direct base class relationship (D,B) and the type of E1 is cv T,
the expression designates the direct base class subobject of type B of the object designated by E1[.](#expr.ref-8.6.sentence-1)
  If E1 is an lvalue,
then E1.E2 is an lvalue;
otherwise, E1.E2 is an xvalue[.](#expr.ref-8.6.sentence-2)
  The type of E1.E2 is âcv Bâ[.](#expr.ref-8.6.sentence-3)
  [*Note [6](#expr.ref-note-6)*:
  This can only occur in an expression of the form e1.[:e2:][.](#expr.ref-8.6.sentence-4)
 â *end note*]
  [*Example [1](#expr.ref-example-1)*: struct B {int b;};struct C : B {int get() const { return b; }};struct D : B, C { };

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

- [(8.7)](#expr.ref-8.7)

  Otherwise, the program is ill-formed[.](#expr.ref-8.7.sentence-1)

[9](#expr.ref-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4332)

If E2 designates a non-static member
(possibly after overload resolution),
the program is ill-formed if the class of which E2 designates
a direct member is an ambiguous base ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup")) of
the designating class ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")) of E2[.](#expr.ref-9.sentence-1)

[*Note [7](#expr.ref-note-7)*:

The program is also ill-formed if the naming class is an ambiguous base of the class type
of the object expression; see [[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")[.](#expr.ref-9.sentence-2)

â *end note*]

[10](#expr.ref-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4343)

If E2 designates a non-static member
(possibly after overload resolution) and
the result of E1 is an object whose type
is not similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to the type of E1,
the behavior is undefined[.](#expr.ref-10.sentence-1)

[*Example [2](#expr.ref-example-2)*: struct A { int i; };struct B { int j; };struct D : A, B {};void f() { D d; static_cast<B&>(d).j; // OK, object expression designates the B subobject of dreinterpret_cast<B&>(d).j; // undefined behavior} â *end example*]

[49)](#footnote-49)[49)](#footnoteref-49)

Note that(*(E1)) is an lvalue[.](#footnote-49.sentence-1)

[50)](#footnote-50)[50)](#footnoteref-50)

If the class member
access expression is evaluated, the subexpression evaluation happens even if the
result is unnecessary to determine
the value of the entire postfix expression, for example if the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denotes a static member[.](#footnote-50.sentence-1)

#### [7.6.1.6](#incr) Increment and decrement [[expr.post.incr]](expr.post.incr)

[1](#incr-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4364)

The value of a postfix ++ expression is the value obtained by
applying the lvalue-to-rvalue conversion ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")) to its operand[.](#incr-1.sentence-1)

[*Note [1](#incr-note-1)*:

The value obtained is a copy of the original value[.](#incr-1.sentence-2)

â *end note*]

The operand shall be a modifiable lvalue[.](#incr-1.sentence-3)

The type of the operand shall
be an arithmetic type other than cv bool,
or a pointer to a complete object type[.](#incr-1.sentence-4)

An operand with volatile-qualified type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#incr-1.sentence-5)

The value of the operand object is modified ([[defns.access]](defns.access "3.1 access"))
as if it were the operand of the prefix ++ operator ([[expr.pre.incr]](expr.pre.incr "7.6.2.3 Increment and decrement"))[.](#incr-1.sentence-6)

Thevalue computation of the ++ expression is sequenced before the
modification of the operand object[.](#incr-1.sentence-7)

With respect to an
indeterminately-sequenced function call, the operation of postfix++ is
a single evaluation[.](#incr-1.sentence-8)

[*Note [2](#incr-note-2)*:

Therefore, a function call cannot intervene between the
lvalue-to-rvalue conversion and the side effect associated with any
single postfix ++ operator[.](#incr-1.sentence-9)

â *end note*]

The result is a prvalue[.](#incr-1.sentence-10)

The type of the result is the cv-unqualified
version of the type of the operand[.](#incr-1.sentence-11)

[2](#incr-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4396)

The operand of postfix -- is decremented analogously to the
postfix ++ operator[.](#incr-2.sentence-1)

[*Note [3](#incr-note-3)*:

For prefix increment and decrement, see [[expr.pre.incr]](expr.pre.incr "7.6.2.3 Increment and decrement")[.](#incr-2.sentence-2)

â *end note*]

#### [7.6.1.7](#expr.dynamic.cast) Dynamic cast [[expr.dynamic.cast]](expr.dynamic.cast)

[1](#expr.dynamic.cast-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4409)

The result of the expression dynamic_cast<T>(v) is the result of
converting the expression v to type T[.](#expr.dynamic.cast-1.sentence-1)

T shall be a pointer or reference to a complete class type, or
âpointer to cv voidâ[.](#expr.dynamic.cast-1.sentence-2)

The dynamic_cast operator shall not cast
away constness ([[expr.const.cast]](#expr.const.cast "7.6.1.11 Const cast"))[.](#expr.dynamic.cast-1.sentence-3)

[2](#expr.dynamic.cast-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4419)

If T is a pointer type, v shall be a prvalue of a
pointer to complete class type, and the result is a prvalue of typeT[.](#expr.dynamic.cast-2.sentence-1)

If T is an lvalue reference type, v shall be
an lvalue of a complete class type, and the result is an lvalue of the
type referred to by T[.](#expr.dynamic.cast-2.sentence-2)

If T is an rvalue reference type,v shall be a glvalue having a complete class type, and the
result is an xvalue of the type referred to by T[.](#expr.dynamic.cast-2.sentence-3)

[3](#expr.dynamic.cast-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4428)

If the type of v is the same as T (ignoring cv-qualifications),
the result isv (converted if necessary)[.](#expr.dynamic.cast-3.sentence-1)

[4](#expr.dynamic.cast-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4433)

If T is âpointer to *cv1* Bâ and v has
type âpointer to *cv2* Dâ such that B is a base
class of D, the result is a pointer to the unique B subobject of the D object pointed to by v, or
a null pointer value if v is a null pointer value[.](#expr.dynamic.cast-4.sentence-1)

Similarly, ifT is âreference to *cv1* Bâ and v has
type *cv2* D such that B is a base class ofD, the result is the unique B subobject of the D object referred to by v[.](#expr.dynamic.cast-4.sentence-2)[51](#footnote-51 "The most derived object ([intro.object]) pointed or referred to by v can contain other B objects as base classes, but these are ignored.")

In both the pointer and
reference cases, the program is ill-formed if B is an inaccessible or
ambiguous base class of D[.](#expr.dynamic.cast-4.sentence-3)

[*Example [1](#expr.dynamic.cast-example-1)*: struct B { };struct D : B { };void foo(D* dp) { B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;} â *end example*]

[5](#expr.dynamic.cast-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4463)

Otherwise, v shall be a pointer to or a glvalue of a[polymorphic type](class.virtual#def:class,polymorphic "11.7.3 Virtual functions [class.virtual]")[.](#expr.dynamic.cast-5.sentence-1)

[6](#expr.dynamic.cast-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4467)

If v is a null pointer value, the result is a null pointer value[.](#expr.dynamic.cast-6.sentence-1)

[7](#expr.dynamic.cast-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4470)

If v has type âpointer to cv Uâ andv does not point to an object
whose type is similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to U and
that is
within its lifetime or
within its period of construction or destruction ([[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")),
the behavior is undefined[.](#expr.dynamic.cast-7.sentence-1)

If v is a glvalue of type U andv does not refer to an object
whose type is similar to U and
that is
within its lifetime or
within its period of construction or destruction,
the behavior is undefined[.](#expr.dynamic.cast-7.sentence-2)

[8](#expr.dynamic.cast-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4486)

If T is âpointer to cv voidâ, then the result
is a pointer to the most derived object pointed to by v[.](#expr.dynamic.cast-8.sentence-1)

Otherwise, a runtime check is applied to see if the object pointed or
referred to by v can be converted to the type pointed or
referred to by T[.](#expr.dynamic.cast-8.sentence-2)

[9](#expr.dynamic.cast-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4493)

Let C be the class type to which T points or refers[.](#expr.dynamic.cast-9.sentence-1)

The runtime
check logically executes as follows:

- [(9.1)](#expr.dynamic.cast-9.1)

  If, in the most derived object pointed (referred) to by v,v points (refers) to a public base class subobject of aC object, and if only one object of type C is derived
from the subobject pointed (referred) to by v,
the result points (refers) to that C object[.](#expr.dynamic.cast-9.1.sentence-1)

- [(9.2)](#expr.dynamic.cast-9.2)

  Otherwise, if v points (refers) to a public base
class subobject of the most derived object, and the type of the most
derived object has a base class, of type C, that is unambiguous
and public, the result points (refers) to theC subobject of the most derived object[.](#expr.dynamic.cast-9.2.sentence-1)

- [(9.3)](#expr.dynamic.cast-9.3)

  Otherwise, the
runtime check [*fails*](#def:fails)[.](#expr.dynamic.cast-9.3.sentence-1)

[10](#expr.dynamic.cast-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4513)

The value of a failed cast to pointer type is the null pointer value of
the required result type[.](#expr.dynamic.cast-10.sentence-1)

A failed cast to reference type [throws
an exception](except.throw "14.2 Throwing an exception [except.throw]") of a type that would match a[handler](except.handle "14.4 Handling an exception [except.handle]") of type [std​::​bad_cast](bad.cast "17.7.4 Class bad_­cast [bad.cast]")[.](#expr.dynamic.cast-10.sentence-2)

[*Example [2](#expr.dynamic.cast-example-2)*: class A { virtual void f(); };class B { virtual void g(); };class D : public virtual A, private B { };void g() { D d;
 B* bp = (B*)&d; // cast needed to break protection A* ap = &d; // public derivation, no cast needed D& dr = dynamic_cast<D&>(*bp); // fails ap = dynamic_cast<A*>(bp); // fails bp = dynamic_cast<B*>(ap); // fails ap = dynamic_cast<A*>(&d); // succeeds bp = dynamic_cast<B*>(&d); // ill-formed (not a runtime check)}class E : public D, public B { };class F : public E, public D { };void h() { F f;
 A* ap = &f; // succeeds: finds unique A D* dp = dynamic_cast<D*>(ap); // fails: yields null; f has two D subobjects E* ep = (E*)ap; // error: cast from virtual base E* ep1 = dynamic_cast<E*>(ap); // succeeds} â *end example*]

[*Note [1](#expr.dynamic.cast-note-1)*:

Subclause [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction") describes the behavior of a dynamic_cast applied to an object under construction or destruction[.](#expr.dynamic.cast-10.sentence-3)

â *end note*]

[51)](#footnote-51)[51)](#footnoteref-51)

The most derived
object ([[intro.object]](intro.object "6.8.2 Object model")) pointed or referred to byv can contain other B objects as base classes, but these
are ignored[.](#footnote-51.sentence-1)

#### [7.6.1.8](#expr.typeid) Type identification [[expr.typeid]](expr.typeid)

[1](#expr.typeid-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4555)

The result of a typeid expression is an lvalue of static typeconst std​::​type_info ([[type.info]](type.info "17.7.3 Class type_­info")) and dynamic type conststd​::​type_info or const *name* where *name* is animplementation-defined class publicly derived fromstd​::​type_info which preserves the behavior described
in [[type.info]](type.info "17.7.3 Class type_­info")[.](#expr.typeid-1.sentence-1)[52](#footnote-52 "The recommended name for such a class is extended_­type_­info.")

The lifetime of the object referred to by the lvalue extends to the end
of the program[.](#expr.typeid-1.sentence-2)

Whether or not the destructor is called for thestd​::​type_info object at the end of the program is unspecified[.](#expr.typeid-1.sentence-3)

[2](#expr.typeid-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4574)

If the type of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") operand is
a (possibly cv-qualified) class type or
a reference to (possibly cv-qualified) class type,
that class shall be completely defined[.](#expr.typeid-2.sentence-1)

[3](#expr.typeid-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4580)

If an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") operand of typeid is
a possibly-parenthesized [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]") whose [*unary-operator*](expr.unary.general#nt:unary-operator "7.6.2.1 General [expr.unary.general]") is * and
whose operand evaluates to a null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")),
the typeid expression throws an exception ([[except.throw]](except.throw "14.2 Throwing an exception"))
of a type that would match a handler of typestd​::​bad_typeid ([[bad.typeid]](bad.typeid "17.7.5 Class bad_­typeid"))[.](#expr.typeid-3.sentence-1)

[*Note [1](#expr.typeid-note-1)*:

In other contexts, evaluating such a [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]") results in undefined behavior ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators"))[.](#expr.typeid-3.sentence-2)

â *end note*]

[4](#expr.typeid-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4595)

When typeid is applied to a glvalue whose type is a
polymorphic class type ([[class.virtual]](class.virtual "11.7.3 Virtual functions")), the result refers to astd​::​type_info object representing the type of the most derived
object ([[intro.object]](intro.object "6.8.2 Object model")) (that is, the dynamic type) to which the
glvalue refers[.](#expr.typeid-4.sentence-1)

[5](#expr.typeid-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4602)

When typeid is applied to an expression other than a glvalue of
a polymorphic class type, the result refers to a std​::​type_info object representing the static type of the expression[.](#expr.typeid-5.sentence-1)

[Lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") conversions are not applied to
the expression[.](#expr.typeid-5.sentence-2)

If the expression is a prvalue,
the [temporary materialization conversion](conv.rval "7.3.5 Temporary materialization conversion [conv.rval]") is applied[.](#expr.typeid-5.sentence-3)

The expression is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]")[.](#expr.typeid-5.sentence-4)

[6](#expr.typeid-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4614)

When typeid is applied to a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"), the result
refers to a std​::​type_info object representing the type of the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")[.](#expr.typeid-6.sentence-1)

If the type of the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") is a reference
to a possibly cv-qualified type, the result of thetypeid expression refers to a std​::​type_info object
representing the cv-unqualified referenced type[.](#expr.typeid-6.sentence-2)

[*Note [2](#expr.typeid-note-2)*:

The [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") cannot denote a function type with
a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#expr.typeid-6.sentence-3)

â *end note*]

[7](#expr.typeid-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4626)

If the type of the expression or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") is a
cv-qualified type, the result of the typeid expression refers
to a std​::​type_info object representing the cv-unqualified
type[.](#expr.typeid-7.sentence-1)

[*Example [1](#expr.typeid-example-1)*: class D { /* ... */ };
D d1;const D d2;

typeid(d1) == typeid(d2); // yields truetypeid(D) == typeid(const D); // yields truetypeid(D) == typeid(d2); // yields truetypeid(D) == typeid(const D&); // yields true â *end example*]

[8](#expr.typeid-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4644)

The type std​::​type_info ([[type.info]](type.info "17.7.3 Class type_­info")) is not predefined;
if a standard library declaration ([[typeinfo.syn]](typeinfo.syn "17.7.2 Header <typeinfo> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules")) ofstd​::​type_info does not precede ([[basic.lookup.general]](basic.lookup.general "6.5.1 General"))
a typeid expression, the program is ill-formed[.](#expr.typeid-8.sentence-1)

[9](#expr.typeid-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4650)

[*Note [3](#expr.typeid-note-3)*:

Subclause [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction") describes the behavior of typeid applied to an object under construction or destruction[.](#expr.typeid-9.sentence-1)

â *end note*]

[52)](#footnote-52)[52)](#footnoteref-52)

The recommended name for such a class isextended_type_info[.](#footnote-52.sentence-1)

#### [7.6.1.9](#expr.static.cast) Static cast [[expr.static.cast]](expr.static.cast)

[1](#expr.static.cast-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4658)

The result of the expression static_cast<T>(v) is the result of
converting the expression v to type T[.](#expr.static.cast-1.sentence-1)

If T is an lvalue reference type
or an rvalue reference to function type, the result is an lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue[.](#expr.static.cast-1.sentence-2)

[2](#expr.static.cast-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4670)

An lvalue of type â*cv1* Bâ, where B is a class
type, can be cast to type âreference to *cv2* Dâ, whereD is a complete class derived ([[class.derived]](class.derived "11.7 Derived classes")) from B,
if *cv2* is the
same cv-qualification as, or greater cv-qualification than,*cv1*[.](#expr.static.cast-2.sentence-1)

If B is a virtual base class of D or a base class of a virtual base class of D,
or if no valid standard conversion from âpointer to Dâ
to âpointer to Bâ exists ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions")), the program is ill-formed[.](#expr.static.cast-2.sentence-2)

An xvalue of type
â*cv1* Bâ can be cast to type ârvalue reference to*cv2* Dâ with the same constraints as for an lvalue of
type â*cv1* Bâ[.](#expr.static.cast-2.sentence-3)

If the object
of type â*cv1* Bâ is actually a base class subobject of an object
of type D, the result refers to the enclosing object of typeD[.](#expr.static.cast-2.sentence-4)

Otherwise, the behavior is undefined[.](#expr.static.cast-2.sentence-5)

[*Example [1](#expr.static.cast-example-1)*: struct B { };struct D : public B { };
D d;
B &br = d;

static_cast<D&>(br); // produces lvalue denoting the original d object â *end example*]

[3](#expr.static.cast-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4700)

An lvalue
of type T1 can be cast to type ârvalue
reference to T2â if T2 is reference-compatible withT1 ([[dcl.init.ref]](dcl.init.ref "9.5.4 References"))[.](#expr.static.cast-3.sentence-1)

If the value is not a bit-field,
the result refers to the object or the specified base class subobject
thereof; otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]") is applied to the bit-field and the resulting prvalue is used as the
operand of the static_cast for the remainder of this subclause[.](#expr.static.cast-3.sentence-2)

If T2 is an inaccessible ([[class.access]](class.access "11.8 Member access control")) or
ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup")) base class of T1,
a program that necessitates such a cast is ill-formed[.](#expr.static.cast-3.sentence-3)

[4](#expr.static.cast-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4713)

Any expression can be explicitly converted to type cv void,
in which case the operand is a discarded-value expression ([[expr.prop]](expr.prop "7.2 Properties of expressions"))[.](#expr.static.cast-4.sentence-1)

[*Note [1](#expr.static.cast-note-1)*:

Such a static_cast has no result
as it is a prvalue of type void; see [[basic.lval]](basic.lval "7.2.1 Value category")[.](#expr.static.cast-4.sentence-2)

â *end note*]

[*Note [2](#expr.static.cast-note-2)*:

However, if the value is in a temporary
object ([[class.temporary]](class.temporary "6.8.7 Temporary objects")), the destructor for that
object is
not executed until the usual time, and the value of the object is
preserved for the purpose of executing the destructor[.](#expr.static.cast-4.sentence-3)

â *end note*]

[5](#expr.static.cast-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4728)

Otherwise, an expression E can be explicitly converted to a type T if there is an implicit conversion sequence ([[over.best.ics]](over.best.ics "12.2.4.2 Implicit conversion sequences"))
from E to T,
if overload resolution for a direct-initialization ([[dcl.init]](dcl.init "9.5 Initializers"))
of an object or reference of type T from E would find at least one viable function ([[over.match.viable]](over.match.viable "12.2.3 Viable functions")), or
if T is an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"))
having a first element x and
there is an implicit conversion sequence
from E to the type of x[.](#expr.static.cast-5.sentence-1)

If T is a reference type, the effect is
the same as performing the declaration and initializationT t(E); for some invented temporary variable t ([[dcl.init]](dcl.init "9.5 Initializers"))
and then using the temporary variable as the result of the conversion[.](#expr.static.cast-5.sentence-2)

Otherwise, the result object is direct-initialized from E[.](#expr.static.cast-5.sentence-3)

[*Note [3](#expr.static.cast-note-3)*:

The conversion is ill-formed when attempting to convert an
expression of class type to an inaccessible or ambiguous base class[.](#expr.static.cast-5.sentence-4)

â *end note*]

[*Note [4](#expr.static.cast-note-4)*:

If T is âarray of unknown bound of Uâ,
this direct-initialization defines the type of the expression as U[1][.](#expr.static.cast-5.sentence-5)

â *end note*]

[6](#expr.static.cast-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4756)

Otherwise, the lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.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")) conversions are applied to the
operand, and the conversions that can be performed using static_cast are listed below[.](#expr.static.cast-6.sentence-1)

No other conversion can be performed using static_cast[.](#expr.static.cast-6.sentence-2)

[7](#expr.static.cast-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4763)

A value of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))
can be explicitly converted to an integral type;
the result is the same as that of converting
to the enumeration's underlying type and then to the destination type[.](#expr.static.cast-7.sentence-1)

A value of a scoped enumeration type
can also be explicitly converted to a floating-point type;
the result is the same as that of converting
from the original value to the floating-point type[.](#expr.static.cast-7.sentence-2)

[8](#expr.static.cast-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4773)

A value of integral or enumeration type can be explicitly converted to
a complete enumeration type[.](#expr.static.cast-8.sentence-1)

If the enumeration type has a fixed underlying type,
the value is first converted to that type
by
integral promotion ([[conv.prom]](conv.prom "7.3.7 Integral promotions")) or integral conversion ([[conv.integral]](conv.integral "7.3.9 Integral conversions")),
if necessary, and
then to the enumeration type[.](#expr.static.cast-8.sentence-2)

If the enumeration type does not have a fixed underlying type,
the value is unchanged
if the original value is within the range
of the enumeration values ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), and
otherwise, the behavior is undefined[.](#expr.static.cast-8.sentence-3)

A value of floating-point type can also be explicitly converted to an enumeration type[.](#expr.static.cast-8.sentence-4)

The resulting value is the same as converting the original value to the
underlying type of the enumeration ([[conv.fpint]](conv.fpint "7.3.11 Floating-integral conversions")), and subsequently to
the enumeration type[.](#expr.static.cast-8.sentence-5)

[9](#expr.static.cast-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4794)

A prvalue of floating-point type can be explicitly converted to
any other floating-point type[.](#expr.static.cast-9.sentence-1)

If the source value can be exactly represented in the destination type,
the result of the conversion has that exact representation[.](#expr.static.cast-9.sentence-2)

If the source value is between two adjacent destination values,
the result of the conversion is
an implementation-defined choice of
either of those values[.](#expr.static.cast-9.sentence-3)

Otherwise, the behavior is undefined[.](#expr.static.cast-9.sentence-4)

[10](#expr.static.cast-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4805)

A prvalue of type âpointer to *cv1* Bâ, where B is a class type, can be converted to a prvalue of type âpointer to*cv2* Dâ,
where D is a complete class[derived](class.derived "11.7 Derived classes [class.derived]") from B,
if *cv2* is the same cv-qualification as,
or greater cv-qualification than, *cv1*[.](#expr.static.cast-10.sentence-1)

If B is a virtual base class of D or
a base class of a virtual base class of D, or
if no valid standard conversion from âpointer to Dâ
to âpointer to Bâ exists ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions")), the program is ill-formed[.](#expr.static.cast-10.sentence-2)

The null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")) is converted
to the null pointer value of the destination type[.](#expr.static.cast-10.sentence-3)

If the prvalue of type
âpointer to *cv1* Bâ points to a B that is
actually a base class subobject of an object of type D, the resulting
pointer points to the enclosing object of type D[.](#expr.static.cast-10.sentence-4)

Otherwise, the
behavior is undefined[.](#expr.static.cast-10.sentence-5)

[11](#expr.static.cast-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4827)

A prvalue of type âpointer to member of D of type *cv1*Tâ can be converted to a prvalue of type âpointer to member ofB of type *cv2* Tâ, whereD is a complete class type andB is a [base class](class.derived "11.7 Derived classes [class.derived]") of D,
if *cv2* is the same cv-qualification
as, or greater cv-qualification than, *cv1*[.](#expr.static.cast-11.sentence-1)

[*Note [5](#expr.static.cast-note-5)*:

Function types (including those used in pointer-to-member-function types)
are never cv-qualified ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#expr.static.cast-11.sentence-2)

â *end note*]

If no valid standard conversion
from âpointer to member of B of type Tâ
to âpointer to member of D of type Tâ
exists ([[conv.mem]](conv.mem "7.3.13 Pointer-to-member conversions")), the program is ill-formed[.](#expr.static.cast-11.sentence-3)

The [null member pointer value](conv.mem#def:value,null_member_pointer "7.3.13 Pointer-to-member conversions [conv.mem]") is converted to the null
member pointer value of the destination type[.](#expr.static.cast-11.sentence-4)

If class B contains the original member, or is a base class of the class
containing the original member, the resulting pointer to member points
to the original member[.](#expr.static.cast-11.sentence-5)

Otherwise, the behavior is undefined[.](#expr.static.cast-11.sentence-6)

[*Note [6](#expr.static.cast-note-6)*:

Although class B need not contain the original member, the
dynamic type of the object with which indirection through the pointer
to member is performed must contain the original member;
see [[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-to-member operators")[.](#expr.static.cast-11.sentence-7)

â *end note*]

[12](#expr.static.cast-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4856)

A prvalue of type âpointer to *cv1* voidâ can be
converted to a prvalue of type âpointer to *cv2* Tâ,
where T is an object type and *cv2* is the same
cv-qualification as, or greater cv-qualification than, *cv1*[.](#expr.static.cast-12.sentence-1)

If the original pointer value represents the addressA of a byte in memory andA does not satisfy the alignment requirement of T,
then the resulting pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")) is unspecified[.](#expr.static.cast-12.sentence-2)

Otherwise, if the original pointer value points to an object *a*,
and there is an object *b* of type similar to T that is [pointer-interconvertible](basic.compound#def:pointer-interconvertible "6.9.4 Compound types [basic.compound]") with *a*,
the result is a pointer to *b*[.](#expr.static.cast-12.sentence-3)

Otherwise, the pointer value is unchanged by the conversion[.](#expr.static.cast-12.sentence-4)

[*Example [2](#expr.static.cast-example-2)*: T* p1 = new T;const T* p2 = static_cast<const T*>(static_cast<void*>(p1));bool b = p1 == p2; // b will have the value true. â *end example*]

#### [7.6.1.10](#expr.reinterpret.cast) Reinterpret cast [[expr.reinterpret.cast]](expr.reinterpret.cast)

[1](#expr.reinterpret.cast-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4880)

The result of the expression reinterpret_cast<T>(v) is the
result of converting the expression v to type T[.](#expr.reinterpret.cast-1.sentence-1)

If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the[lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") standard conversions are
performed on the expression v[.](#expr.reinterpret.cast-1.sentence-2)

Conversions that can be performed explicitly
using reinterpret_cast are listed below[.](#expr.reinterpret.cast-1.sentence-3)

No other conversion can
be performed explicitly using reinterpret_cast[.](#expr.reinterpret.cast-1.sentence-4)

[2](#expr.reinterpret.cast-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4896)

The reinterpret_cast operator shall not cast away constness ([[expr.const.cast]](#expr.const.cast "7.6.1.11 Const cast"))[.](#expr.reinterpret.cast-2.sentence-1)

An expression of integral, enumeration, pointer, or pointer-to-member type
can be explicitly converted to its own type; such a cast yields the value of
its operand[.](#expr.reinterpret.cast-2.sentence-2)

[3](#expr.reinterpret.cast-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4902)

[*Note [1](#expr.reinterpret.cast-note-1)*:

The mapping performed by reinterpret_cast might, or might not, produce a
representation different from the original value[.](#expr.reinterpret.cast-3.sentence-1)

â *end note*]

[4](#expr.reinterpret.cast-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4908)

A pointer can be explicitly converted to any integral type large enough
to hold all values of its type[.](#expr.reinterpret.cast-4.sentence-1)

The mapping function is implementation-defined[.](#expr.reinterpret.cast-4.sentence-2)

[*Note [2](#expr.reinterpret.cast-note-2)*:

It is intended to be unsurprising to those who know the addressing
structure of the underlying machine[.](#expr.reinterpret.cast-4.sentence-3)

â *end note*]

A value of type std​::​nullptr_t can be converted to an integral
type; the conversion has the same meaning and validity as a conversion of(void*)0 to the integral type[.](#expr.reinterpret.cast-4.sentence-4)

[*Note [3](#expr.reinterpret.cast-note-3)*:

A reinterpret_cast cannot be used to convert a value of any type to the typestd​::​nullptr_t[.](#expr.reinterpret.cast-4.sentence-5)

â *end note*]

[5](#expr.reinterpret.cast-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4928)

A value of integral type or enumeration type can be explicitly converted
to a pointer[.](#expr.reinterpret.cast-5.sentence-1)

A pointer converted to an integer of sufficient size (if
any such exists on the implementation) and back to the same pointer type
will have its original value ([[basic.compound]](basic.compound "6.9.4 Compound types"));mappings between pointers and integers are otherwiseimplementation-defined[.](#expr.reinterpret.cast-5.sentence-2)

[6](#expr.reinterpret.cast-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4939)

A function pointer can be explicitly converted
to a function pointer of a different type[.](#expr.reinterpret.cast-6.sentence-1)

[*Note [4](#expr.reinterpret.cast-note-4)*:

The effect of calling a function through a pointer to a function
type ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) that is not the same as the type used in the
definition of the function is undefined ([[expr.call]](#expr.call "7.6.1.3 Function call"))[.](#expr.reinterpret.cast-6.sentence-2)

â *end note*]

Except that converting
a prvalue of type âpointer to T1â to the type âpointer toT2â (where T1 and T2 are function types) and
back to its original type yields the original pointer value, the result
of such a pointer conversion is unspecified[.](#expr.reinterpret.cast-6.sentence-3)

[7](#expr.reinterpret.cast-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4957)

An object pointer
can be explicitly converted to an object pointer of a different type[.](#expr.reinterpret.cast-7.sentence-1)[53](#footnote-53 "The types can have different cv-qualifiers, subject to the overall restriction that a reinterpret_­cast cannot cast away constness.")

When a prvalue v of object pointer type is converted to
the object pointer type âpointer to cv Tâ, the result is static_cast<cv T*>(static_cast<cv void*>(v))[.](#expr.reinterpret.cast-7.sentence-2)

[*Note [5](#expr.reinterpret.cast-note-5)*:

Converting a pointer of type âpointer to T1â
that points to an object of type T1 to the type âpointer to T2â
(where T2 is an object type
and the alignment requirements of T2 are no stricter than those of T1)
and back to its original type yields the original pointer value[.](#expr.reinterpret.cast-7.sentence-3)

â *end note*]

[8](#expr.reinterpret.cast-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4978)

Converting a function pointer to an object pointer
type or vice versa is
conditionally-supported[.](#expr.reinterpret.cast-8.sentence-1)

The meaning of such a conversion isimplementation-defined,
except that if an implementation
supports conversions in both directions, converting a prvalue of one type to the other
type and back, possibly with different cv-qualification, shall yield the original
pointer value[.](#expr.reinterpret.cast-8.sentence-2)

[9](#expr.reinterpret.cast-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4988)

The null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")) is converted to the null pointer value
of the destination type[.](#expr.reinterpret.cast-9.sentence-1)

[*Note [6](#expr.reinterpret.cast-note-6)*:

A null pointer constant of type std​::​nullptr_t cannot be converted to a
pointer type, and a null pointer constant of integral type is not necessarily
converted to a null pointer value[.](#expr.reinterpret.cast-9.sentence-2)

â *end note*]

[10](#expr.reinterpret.cast-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4997)

A prvalue of type âpointer to member of X of type T1â
can be explicitly converted to a prvalue of a different type âpointer to member ofY of type T2â if T1 and T2 are both
function types or both object types[.](#expr.reinterpret.cast-10.sentence-1)[54](#footnote-54 "T1 and T2 can have different cv-qualifiers, subject to the overall restriction that a reinterpret_­cast cannot cast away constness.")

The null member pointer value ([[conv.mem]](conv.mem "7.3.13 Pointer-to-member conversions")) is converted to the
null member pointer value of the destination type[.](#expr.reinterpret.cast-10.sentence-2)

The result of this
conversion is unspecified, except in the following cases:

- [(10.1)](#expr.reinterpret.cast-10.1)

  Converting a prvalue of type âpointer to member functionâ to a
different pointer-to-member-function type and back to its original type
yields the original pointer-to-member value[.](#expr.reinterpret.cast-10.1.sentence-1)

- [(10.2)](#expr.reinterpret.cast-10.2)

  Converting a prvalue of type âpointer to data member of X of type T1â to the type âpointer to data member of Y of type T2â (where the alignment requirements of T2 are
no stricter than those of T1) and back to its original type
yields the original pointer-to-member value[.](#expr.reinterpret.cast-10.2.sentence-1)

[11](#expr.reinterpret.cast-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5025)

If v is a glvalue of type T1,
designating an object or function *x*,
it can be cast to the type âreference to T2â
if an expression of type âpointer to T1â
can be explicitly converted to the type âpointer to T2â
using a reinterpret_cast[.](#expr.reinterpret.cast-11.sentence-1)

The result is that of *reinterpret_cast<T2 *>(p) where p is a pointer to *x* of type âpointer to T1â[.](#expr.reinterpret.cast-11.sentence-2)

[*Note [7](#expr.reinterpret.cast-note-7)*:

No temporary is materialized ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) or created,
no copy is made, and
no constructors ([[class.ctor]](class.ctor "11.4.5 Constructors")) or conversion
functions ([[class.conv]](class.conv "11.4.8 Conversions")) are called[.](#expr.reinterpret.cast-11.sentence-3)[55](#footnote-55 "This is sometimes referred to as a type pun when the result refers to the same object as the source glvalue.")

â *end note*]

[53)](#footnote-53)[53)](#footnoteref-53)

The
types can have different cv-qualifiers, subject to
the overall
restriction that a reinterpret_cast cannot cast away constness[.](#footnote-53.sentence-1)

[54)](#footnote-54)[54)](#footnoteref-54)

T1 and T2 can have
different cv-qualifiers, subject to
the overall restriction that a reinterpret_cast cannot cast away
constness[.](#footnote-54.sentence-1)

[55)](#footnote-55)[55)](#footnoteref-55)

This is sometimes referred to as a type pun
when the result refers to the same object as the source glvalue[.](#footnote-55.sentence-1)

#### [7.6.1.11](#expr.const.cast) Const cast [[expr.const.cast]](expr.const.cast)

[1](#expr.const.cast-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5051)

The result of the expression const_cast<T>(v) is of typeT[.](#expr.const.cast-1.sentence-1)

If T is an lvalue reference to object type, the result is an
lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue and the[lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") standard conversions are
performed on the expression v[.](#expr.const.cast-1.sentence-2)

The [temporary materialization conversion](conv.rval "7.3.5 Temporary materialization conversion [conv.rval]") is not
performed on v, other than as specified below[.](#expr.const.cast-1.sentence-3)

Conversions that can be performed explicitly usingconst_cast are listed below[.](#expr.const.cast-1.sentence-4)

No other conversion shall be
performed explicitly using const_cast[.](#expr.const.cast-1.sentence-5)

[2](#expr.const.cast-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5068)

[*Note [1](#expr.const.cast-note-1)*:

Subject to the restrictions in this subclause, an expression can be cast
to its own type using a const_cast operator[.](#expr.const.cast-2.sentence-1)

â *end note*]

[3](#expr.const.cast-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5074)

For two similar object pointer or pointer to data member typesT1 and T2 ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")),
a prvalue of type T1 can be explicitly
converted to the type T2 using a const_cast if, considering the qualification-decompositions of both types,
each P1i is the same as P2i for all i[.](#expr.const.cast-3.sentence-1)

If v is a null pointer or null member pointer,
the result is a null pointer or null member pointer, respectively[.](#expr.const.cast-3.sentence-2)

Otherwise, the result points to or past the end of the same object, or
points to the same member, respectively, as v[.](#expr.const.cast-3.sentence-3)

[4](#expr.const.cast-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5086)

For two object types T1 and T2, if a pointer to T1 can
be explicitly converted to the type âpointer to T2â using aconst_cast, then the following conversions can also be made:

- [(4.1)](#expr.const.cast-4.1)

an lvalue of type T1 can be explicitly converted to an lvalue
of type T2 using the cast const_cast<T2&>;

- [(4.2)](#expr.const.cast-4.2)

a glvalue of type T1 can be explicitly converted to an xvalue
of type T2 using the cast const_cast<T2&&>; and

- [(4.3)](#expr.const.cast-4.3)

if T1 is a class or array type,
a prvalue of type T1 can be
explicitly converted to an xvalue of type T2 using the castconst_cast<T2&&>[.](#expr.const.cast-4.sentence-1)
  The temporary materialization conversion is performed on v[.](#expr.const.cast-4.3.sentence-2)

The result refers to the same object as the (possibly converted) operand[.](#expr.const.cast-4.sentence-2)

[*Example [1](#expr.const.cast-example-1)*: typedef int *A[3]; // array of 3 pointer to inttypedef const int *const CA[3]; // array of 3 const pointer to const intauto &&r2 = const_cast<A&&>(CA{}); // OK, temporary materialization conversion is performed â *end example*]

[5](#expr.const.cast-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5114)

[*Note [2](#expr.const.cast-note-2)*:

Depending on the type of the object, a write operation through the
pointer, lvalue or pointer to data member resulting from aconst_cast that casts away a const-qualifier[56](#footnote-56 "const_­cast is not limited to conversions that cast away a const-qualifier.") can produce undefined behavior ([[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers"))[.](#expr.const.cast-5.sentence-1)

â *end note*]

[6](#expr.const.cast-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5127)

A conversion from a type T1 to a type T2[*casts away constness*](#def:casting_away_constness "7.6.1.11 Const cast [expr.const.cast]") if T1 and T2 are different,
there is a qualification-decomposition ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) of T1 yielding *n* such thatT2 has a qualification-decomposition of the formcv20 P20 cv21 P21 â¯ cv2nâ1 P2nâ1 cv2n U2, and there is no qualification conversion that converts T1 tocv20 P10 cv21 P11 â¯ cv2nâ1 P1nâ1 cv2n U1[.](#expr.const.cast-6.sentence-1)

[7](#expr.const.cast-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5143)

Casting from an lvalue of type T1 to an lvalue of typeT2 using an lvalue reference cast
or casting from an expression of type T1 to an xvalue of type T2 using
an rvalue reference cast
casts away constness if a cast from a prvalue of type âpointer to T1â to the type âpointer toT2â casts away constness[.](#expr.const.cast-7.sentence-1)

[8](#expr.const.cast-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5151)

[*Note [3](#expr.const.cast-note-3)*:

Some conversions which involve only changes in cv-qualification cannot
be done using const_cast[.](#expr.const.cast-8.sentence-1)

For instance, conversions between
pointers to functions are not covered because such conversions lead to
values whose use causes undefined behavior[.](#expr.const.cast-8.sentence-2)

For the same reasons,
conversions between pointers to member functions, and in particular, the
conversion from a pointer to a const member function to a pointer to a
non-const member function, are not covered[.](#expr.const.cast-8.sentence-3)

â *end note*]

[56)](#footnote-56)[56)](#footnoteref-56)

const_cast is not limited to conversions that cast away a
const-qualifier[.](#footnote-56.sentence-1)
