-
[Note: Clause 5 defines the syntax, order of evaluation, and meaning of expressions.
An expression is a sequence of operators and operands that specifies a computation.
An expression can result in a value and can cause side effects.
-
Operators can be overloaded, that is, given meaning when applied to expressions of class type (clause 9) or enumeration type (7.2).
Uses of overloaded operators are transformed into function calls as described in 13.5.
Overloaded operators obey the rules for syntax specified in clause 5, but the requirements of operand type, lvalue, and evaluation order are replaced by the rules for function call.
Relations between operators, such as ++a meaning a+=1, are not guaranteed for overloaded operators (13.5), and are not guaranteed for operands of type bool.
--end note]
- Clause 5 defines the effects of operators when applied to types for which they have not been overloaded. Operator overloading shall not modify the rules for the builtin operators, that is, for operators applied to types for which they are defined by this Standard.
However, these builtin operators participate in overload resolution, and as part of that process userdefined conversions will be considered where necessary to convert the operands to types appropriate for the builtin operator.
If a builtin operator is selected, such conversions will be applied to the operands before the operation is considered further according to the rules in clause 5; see 13.3.1.2, 13.6.
-
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified 53).
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the value to be stored.
The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
[Example:
i = v[ i++]; // the
behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++ i + 1; // the
behavior is unspecified
i = i + 1;
// the value of i is incremented
--end example]
-
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined, unless such an expression is a constant expression (5.19), in which case the program is illformed.
[Note: most existing implementations of C++ ignore integer overflows.
Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is usually adjustable by a library function. ]
-
If an expression initially has the type "reference to T" (8.3.2, 8.5.3), the type is adjusted to "T" prior to any further analysis, the expression designates the object or function denoted by the reference, and the expression is an lvalue.
-
An expression designating an object is called an objectexpression.
-
Whenever an lvalue expression appears as an operand of an operator that expects an rvalue for that operand, the lvaluetorvalue (4.1), arraytopointer (4.2), or functiontopointer (4.3) standard conversions are applied to convert the expression to an rvalue.
[Note: because cvqualifiers are removed from the type of an expression of nonclass type when the expression is converted to an rvalue, an lvalue expression of type const int can, for example, be used where an rvalue expression of type int is required. ]
-
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way.
The purpose is to yield a common type, which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
-
If either operand is of type long double, the other shall be converted to long double.
-
Otherwise, if either operand is double, the other shall be converted to double.
-
Otherwise, if either operand is float, the other shall be converted to float.
-
Otherwise, the integral promotions (4.5) shall be performed on both operands 54).
-
Then, if either operand is unsigned long the other shall be converted to unsigned long.
-
Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
-
Otherwise, if either operand is long, the other shall be converted to long.
-
Otherwise, if either operand is unsigned, the other shall be converted to unsigned.
[Note: otherwise, the only remaining case is that both operands are int ]
-
The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby 55).
5.1 Primary expressions
|
[expr.prim]
|
-
Primary expressions are literals, names, and names qualified by the scope resolution operator ::.
primaryexpression:
literal
this
( expression )
idexpression
idexpression:
unqualifiedid
qualifiedid
unqualifiedid:
identifier
operatorfunctionid
conversionfunctionid
~ classname
templateid
-
A literal is a primary expression.
Its type depends on its form (2.13).
A string literal is an lvalue; all other literals are rvalues.
-
The keyword this names a pointer to the object for which a nonstatic member function (9.3.2) is invoked. The keyword this shall be used only inside a nonstatic class member function body (9.3) or in a constructor meminitializer (12.6.2).
The type of the expression is a pointer to the function's class (9.3.2), possibly
with cvqualifiers on the class type.
The expression is an rvalue.
-
The operator :: followed by an identifier, a qualifiedid, or an operatorfunctionid is a primaryexpression.
Its type is specified by the declaration of the identifier, qualifiedid, or operatorfunctionid.
The result is the entity denoted by the identifier, qualifiedid, or operatorfunctionid.
The result is an lvalue if the entity is a function or variable.
The identifier, qualifiedid, or operatorfunctionid shall have global namespace scope or be visible in global scope because of a usingdirective (7.3.4).
[Note: the use of :: allows a type, an object, a function, an enumerator, or a namespace declared in the global namespace to be referred to even if its identifier has been hidden (3.4.3). ]
-
A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression.
The presence of parentheses does not affect whether the expression is an lvalue.
The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated.
-
An idexpression is a restricted form of a primaryexpression.
[Note: an idexpression can appear after . and > operators (5.2.5). ]
-
An identifier is an idexpression provided it has been suitably declared (clause 7).
[Note: for operatorfunctionids, see 13.5; for conversionfunctionids, see 12.3.2; for templateids, see 14.2.
A classname prefixed by ~ denotes a destructor; see 12.4.
Within the definition of a nonstatic member function, an identifier that names a nonstatic member is transformed to a class member access expression (9.3.1)].
The type of the expression is the type of the identifier.
The result is the entity denoted by the identifier.
The result is an lvalue if the entity is a function, variable, or data member.
qualifiedid:
:: opt nestednamespecifier templateopt unqualifiedid
:: identifier
:: operatorfunctionid
:: templateid
nestednamespecifier:
classornamespacename :: nestednamespecifieropt
classornamespacename :: template nestednamespecifier
classornamespacename:
classname
namespacename
A nestednamespecifier that names a class, optionally
followed by the keyword template (14.8.1), and then followed by
the name of a member of either that class (9.2) or one of its base classes
(clause 10), is a qualifiedid; 3.4.3.1 describes name lookup
for class members that appear in qualifiedids.
The result is
the member.
The type of the result is the type of the member. The result
is an lvalue if the member is a static member function or a data member.
[Note: a class member can be referred to using a qualifiedid
at
any point in its potential scope (3.3.6). ] Where classname
::
class
name is used, and the two classnames
refer to the same
class, this notation names the constructor (12.1). Where class
name :: ~ classname is used, the two classnames
shall
refer to the same class; this notation names the destructor (12.4). [Note:
a typedefname that names a class is a classname
(7.1.3).
Except as the identifier
in the declarator for a constructor
or destructor definition outside of a class memberspecification
(12.1,
12.4), a typedefname
that names a class may be used in a qualifiedid
to
refer to a constructor or destructor. ]
-
A nestednamespecifier that names a namespace (7.3), followed
by the name of a member of that namespace (or the name of a member of a
namespace made visible by a usingdirective ) is a qualifiedid;
3.4.3.2
describes name lookup for namespace members that appear in
qualifiedids.
The
result is the member. The type of the result is the type of the member.
The result is an lvalue if the member is a function or a variable.
-
In a qualifiedid, if the idexpression is a conversionfunctionid,
its
conversiontype
id shall denote the same type in both the context in which the entire
qualifiedid
occurs and in the context of the class denoted by the nestednamespecifier.
-
An idexpression that denotes a nonstatic data member or nonstatic
member function of a class can only be used:
-
as part of a class member access (5.2.5) in which the objectexpression
refers to the member's class or a
class derived from that class, or
-
to form a pointer to member (5.3.1), or
-
in the body of a nonstatic member function of that class or of a class
derived from that class (9.3.1), or
-
in a meminitializer for a constructor for that class or for
a class derived from that class (12.6.2).
-
A templateid shall be used as an unqualifiedide
only
as specified in 14.7.2, 14.7, and 14.5.4.
5.2 Postfix expressions
|
[expr.post]
|
-
Postfix expressions group lefttoright.
postfixexpression:
primaryexpression
postfixexpression
[
expression
]
postfixexpression
(
expression
listopt)
simpletype
specifier ( expressionlistop )
typename :: opt
nestednamespecifier identifier
(
expression
listop )
typename :: opt
nestednamespecifier templateopt
template
id ( expressionlistop )
postfixexpression
.
templateopt idexpression
postfixexpression
>
templateopt idexpression
postfixexpression
.
pseudodestructorname
postfixexpression
>
pseudodestructorname
postfixexpression
++
postfixexpression
dynamic_cast
< typeid > ( expression
)
static_cast <
typeid
>
( expression
)
reinterpret_cast
< typeid > ( expression
)
const_cast <
typeid
>
( expression
)
typeid ( expression
)
typeid ( type
id )
expressionlist:
assignmentexpression
expressionlist
,
assignmentexpression
pseudodestructorname:
:: opt
nestednamespecifieropt typename
:: ~
typename
:: opt
nestednamespecifier
template
template
id :: ~ typename
:: opt
nestednamespecifieropt~
typename
5.2.1 Subscripting
|
[expr.sub]
|
-
A postfix expression followed by an expression in square brackets is a
postfix expression. One of the expressions shall have the type "pointer
to T" and the other shall have enumeration or integral type. The
result is an lvalue of type "T." The type "T" shall be a completelydefined
object type. 56) The expression E1[ E2]
is
identical (by definition) to *(( E1)+( E2)).
[Note: see
5.3 and 5.7 for details of
* and + and 8.3.4 for details
of arrays. ]
5.2.2 Function call
|
[expr.call]
|
-
There are two kinds of function call: ordinary function call and member
function 57) (9.3) call. A function call
is a postfix expression followed by parentheses containing a possibly empty,
commaseparated list of expressions which constitute the arguments
to the function. For an ordinary function call, the postfix expression
shall be either an lvalue that refers to a function (in which case the
functiontopointer standard conversion (4.3) is suppressed on
the postfix expression), or it shall have pointer to function type. Calling
a function through an expression whose function type has a language linkage
that is different from the
language linkage of the function type of the called function's definition
is undefined (7.5). For a member function call, the postfix expression
shall be an implicit (9.3.1, 9.4) or explicit class member access (5.2.5)
whose idexpression is a function member name, or a pointer-tomember
expression (5.5) selecting a function member. The first expression in the
postfix expression is then called the object expression,
and the
call is as a member of the object pointed to or referred to. In the case
of an implicit class member access, the implied object is the one pointed
to by this. [Note: a member function call of the form
f()
is
interpreted as (* this). f() (see 9.3.1). ] If a function or member
function name is used, the name can be overloaded (clause 13), in
which case the appropriate function shall be selected according to the
rules in 13.3. The function called in a member function call is normally
selected according to the static type of the object expression (clause
10), but if that function is virtual and is not specified using
a qualifiedid then the function actually called will be the
final overrider (10.3) of the selected function in the dynamic type of
the object expression [Note: the dynamic type is the type of the
object pointed or referred to by the current value of the object expression.
12.7 describes the behavior of virtual function calls when the objectexpression
refers to an object under construction or destruction. ]
-
If no declaration of the called function is visible from the scope of the
call the program is illformed.
-
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. This type shall
be a complete object type, a reference type or the type void.
-
When a function is called, each parameter (8.3.5) shall be initialized
(8.5, 12.8, 12.1) with its corresponding argument. When a function is called,
the parameters that have object type shall have completelydefined
object type. [Note: this still allows a parameter to be a pointer
or reference to an incomplete class type. However, it prevents a passed
byvalue parameter to have an incomplete class type. ] During the initialization
of a parameter, an implementation may avoid the construction of extra temporaries
by combining the conversions on the associated argument and/ or the construction
of temporaries with the initialization of the parameter (see 12.2). The
lifetime of a parameter ends when the function in which it is defined returns.
The initialization and destruction of each parameter occurs within the
context of the calling function. [Example: the access of the constructor,
conversion functions or destructor is checked at the point of call in the
calling function. If a constructor or destructor for a function parameter
throws an exception, the search for a handler starts in the scope of the
calling function; in particular, if the function called has a functiontryblock
(clause
15) with a handler that could handle the exception, this handler is not
considered. ] The value of a function call is the value returned by the
called function 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.
-
[Note: a function can change the values of its nonconst parameters,
but these changes cannot affect the values of the arguments except
where a parameter is of a reference type (8.3.2); if the reference is to
a constqualified type, const_cast is required to be used
to cast away the constness in order to modify the argument's value. Where
a parameter is of const reference type a temporary object is introduced
if needed (7.1.5, 2.13, 2.13.4, 8.3.4, 12.2). In addition, it is possible
to modify the values of nonconstant objects through pointer parameters.
]
-
A function can be declared to accept fewer arguments (by declaring default
arguments (8.3.6)) or more arguments (by using the ellipsis, ...
8.3.5)
than the number of parameters in the function definition (8.4). [Note:
this implies that, except where the ellipsis (...) is used, a parameter
is available for each argument. ]
-
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
(18.7). The lvaluetorvalue (4.1),
arraytopointer (4.2), and functiontopointer (4.3) standard
conversions are performed on the argument expression. After these conversions,
if the argument does not have arithmetic, enumeration, pointer, pointer
to member, or class type, the program is illformed. If the argument
has a nonPOD class type (clause 9), the behavior is undefined. If
the argument has integral or enumeration type that is subject to the integral
promotions (4.5), or a floating point type that is subject to the floating
point promotion (4.6), the value of the argument is converted to the promoted
type before the call. These promotions are referred to as the default
argument promotions.
-
The order of evaluation of arguments is unspecified. All side effects of
argument expression evaluations take effect before the function is entered.
The order of evaluation of the postfix expression and the argument
expression list is unspecified.
-
Recursive calls are permitted, except to the function named main
(3.6.1).
-
A function call is an lvalue if and only if the result type is a reference.
5.2.3 Explicit type conversion (functional notation)
|
[expr.type.conv]
|
-
A simpletypespecifier (7.1.5) followed by a parenthesized
expression
list constructs a value of the specified type given the expression
list. If the expression list is a single expression, the type conversion
expression is equivalent (in definedness, and if defined in meaning) to
the corresponding cast expression (5.4). If the simpletypespecifier
specifies
a class type, the class type shall be complete. If the expression list
specifies more than a single value, the type shall be a class with a suitably
declared constructor (8.5, 12.1), and the expression
T( x1, x2, ...)
is
equivalent in effect to the declaration T t( x1, x2, ...);
for
some invented temporary variable t, with the result being the
value of t as an rvalue.
-
The expression T(), where T is a simpletypespecifier
(7.1.5.2) for a nonarray complete object type or the (possibly cvqualified)
void type, creates an rvalue of the specified type, whose value is determined
by defaultinitialization (8.5; no initialization is done for the
void()
case).
[Note: if T is a nonclass type that is cvqualified,
the
cvqualifiers
are
ignored when determining the type of the resulting rvalue (3.10).]
5.2.4 Pseudo destructor call
|
[expr.type.pseudo];
|
-
The use of a pseudodestructorname after a dot
.
or
arrow > operator represents the destructor for the non
class type named by typename. The result shall only be used
as the operand for the function call operator (), and the result
of such a call has type void. The only effect is the evaluation
of the postfixexpression before the dot or arrow.
-
The left hand side of the dot operator shall be of scalar type. The left
hand side of the arrow operator shall be of pointer to scalar type. This
scalar type is the object type. The type designated by the pseudodestructor
name shall be the same as the object type. Furthermore, the two type
names in a pseudodestructorname of the form
:: opt nestednamespecifier
opt typename
:: ~ typename
shall designate the same scalar type. The cvunqualified
versions of the object type and of the type designated by the pseudo
destructorname shall be the same type.
5.2.5 Class member access
|
[expr.ref]
|
-
A postfix expression followed by a dot . or an arrow >,
optionally
followed by the keyword template (14.8.1), and then followed by
an idexpression, is a postfix expression. The postfix expression
before the dot or arrow is evaluated; 58)
the result of that evaluation, together with the idexpression,
determine
the result of the entire postfix expression.
-
For the first option (dot) the type of the first expression (the object
expression) shall be "class object" (of a complete type). For the second
option (arrow) the type of the first expression (the pointer expression)
shall
be "pointer to class object" (of a complete type). In these cases, the
idexpression
shall
name a member of the class or of one of its base classes. [Note:
because the name of a class is inserted in its class scope (clause 9),
the name of a class is also considered a nested member of that class. ]
[Note: 3.4.5 describes how names are looked up after the . and
>
operators. ]
-
If E1 has the type "pointer to class X," then the expression
E1>
E2 is converted to the equivalent form
(*( E1)). E2; the
remainder of 5.2.5 will address only the first option (dot) 59)
. Abbreviating objectexpression. idexpression
as E1.
E2, then the type and lvalue properties of this expression are determined
as follows. In the remainder of 5.2.5, cq represents either const
or
the absence of const; vq represents either volatile
or
the absence of volatile. cv
represents an arbitrary set
of cvqualifiers, as defined in 3.9.3.
-
If E2 is declared to have type "reference to T", then
E1.
E2 is an lvalue; the type of E1. E2 is T. Otherwise,
one of the following rules applies.
-
If E2 is 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. The type of E1. E2 is T.
-
If E2 is a nonstatic data member, and the type of E1
is
"cq1 vq1 X", and the type of E2 is "cq2
vq2
T",
the
expression designates the named member of the object designated by the
first expression. If E1 is an lvalue, then E1. E2 is
an lvalue. Let the notation vq12
stand for the "union" of vq1
and
vq2 ; that is, if vq1 or vq2
is
volatile,
then
vq12 is
volatile.
Similarly, let the notation
cq12 stand
for the "union" of cq1 and cq2;
that is, if cq1 or
cq2
is const,
then
cq12
is
const.
If
E2
is declared to be a mutable member, then the type of E1.
E2 is "vq12
T". If E2
is not declared to be a mutable
member, then the type of E1. E2 is "cq12 vq12 T".
-
If E2 is a (possibly overloaded) member function, function overload
resolution (13.3) is used to determine whether E1. E2 refers
to a static or a nonstatic member function.
-
If it refers to a static member function, and the type of E2
is
"function of (parameter type list) returning T", then E1.
E2 is an lvalue; the expression designates the static member function.
The type of E1. E2 is the same type as that of E2, namely
"function of (parameter type list) returning T".
-
Otherwise, if E1. E2 refers to a nonstatic member function,
and the type of E2 is "function of (parameter type list) cv
returning
T",
then
E1. E2 is not an lvalue. The expression designates a nonstatic
member function. The expression can be used only as the lefthand operand
of a member function call (9.3). [Note: any redundant set of parentheses
surrounding the expression is ignored (5.1). ] The type of E1. E2 is
"function of (parameter type list)
cv
returning T".
-
If E2 is a nested type, the expression E1. E2 is ill
formed.
-
If E2 is a member enumerator, and the type of E2
is
T,
the
expression E1. E2 is not an lvalue. The type of E1. E2 is
T
-
[Note: "class objects" can be structures (9.2) and unions (9.5).
Classes are discussed in clause 9. ]
5.2.6 Increment and decrement
|
[expr.post.incr]
|
-
The value obtained by applying a postfix ++ is the value that
the operand had before applying the operator. [Note: the value obtained
is a copy of the original value ] The operand shall be a modifiable lvalue.
The type of the operand shall be an arithmetic type or a pointer to a complete
object type. After the result is noted, the value of the object is modified
by adding 1 to it, unless the object is of type bool, in
which case it is set to true. [Note: this use is deprecated,
see annex D. ] The result is an rvalue. The type of the result is the cvunqualified
version of the type of the operand. See also 5.7 and 5.17.
-
The operand of postfix is decremented analogously to
the postfix ++ operator, except that the operand shall not be
of type bool. [Note: For prefix increment and decrement,
see 5.3.2. ]
5.2.7 Dynamic cast
|
[expr.dynamic.cast]
|
-
The result of the expression dynamic_cast< T>( v) is the result
of converting the expression v to type T. T shall be
a pointer or reference to a complete class type, or "pointer to cv
void".
Types
shall not be defined in a dynamic_cast.
The dynamic_cast
operator
shall not cast away constness (5.2.11).
-
If T is a pointer type, v shall be an rvalue of a pointer
to complete class type, and the result is an rvalue of type T.
If
T
is
a 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.
-
If the type of v is the same as the required result type (which,
for convenience, will be called R in this description), or it
is the same as R except that the class object type in R
is
more cvqualified than the class object type in v, the result
is v (converted if necessary).
-
If the value of v is a null pointer value in the pointer case,
the result is the null pointer value of type R.
-
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 sub
object of the D object pointed to by v. Similarly, if
T
is
"reference to cv1
B" and v has type "cv2
D"
such
that B is a base class of D, the result is an lvalue
for the unique 60) B
subobject
of the
D
object referred to by v. In both the pointer
and reference cases, cv1 shall be the same cvqualification
as, or greater cvqualification than, cv2, and B shall
be an accessible unambiguous base class of D. [Example:
struct B {};
struct D : B {};
void foo( D* dp)
{
B* bp = dynamic_cast<
B*>( dp); // equivalent to B* bp = dp;
}
--end example]
-
Otherwise, v shall be a pointer to or an lvalue of a polymorphic
type (10.3).
-
If T is "pointer to cv void," then the result
is a pointer to the most derived object pointed to by v. 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.
-
The runtime check logically executes as follows:
-
If, in the most derived object pointed (referred) to by v, v points
(refers) to a public base class subobject of a T object,
and if only one object of type T is derived from the sub
object pointed (referred) to by v, the result is a pointer (an
lvalue referring) to that
T
object.
-
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 an unambiguous public base class of type T, the
result is a pointer an lvalue referring) to the T subobject
of the most derived object.
-
Otherwise, the runtime check fails.
-
The value of a failed cast to pointer type is the null pointer value of
the required result type. A failed cast to reference type throws bad_cast
(18.5.2).
[Example:
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); // fails
}
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 0
// f has two D subobjects
E* ep = (E*) ap;
// illformed:
// cast from virtual base
E* ep1 = dynamic_cast<
E*>( ap); // succeeds
}
--end example] [Note: 12.7 describes the behavior of a
dynamic_cast
applied
to an object under construction or destruction. ]
5.2.8 Type identification
|
[expr.typeid]
|
-
The result of a typeid expression is an lvalue of static type
const
std:: type_info (18.5.1) and dynamic type const std:: type_info
or
const name
where
name
is an implementationdefined
class derived from std:: type_info
which preserves the behavior
described in 18.5.1. 61) The lifetime of
the object referred to by the lvalue extends to the end of the program.
Whether or not the destructor is called for the type_info object
at the end of the program is unspecified.
-
When typeid is applied to an lvalue expression whose type is a
polymorphic class type (10.3), the result refers to a type_info
object
representing the type of the most derived object (1.8) (that is, the dynamic
type) to which the lvalue refers. If the lvalue expression is obtained
by applying the unary * operator to a pointer 62)
and the pointer is a null pointer value (4.10), the typeid
expression
throws the
bad_typeid exception (18.5.3).
-
When typeid is applied to an expression other than an lvalue of
a polymorphic class type, the result refers to a type_info object
representing the static type of the expression. Lvaluetorvalue
(4.1), arraytopointer (4.2), and functiontopointer
(4.3) conversions are not applied to the expression. If the type of the
expression is a class type, the class shall be completelydefined.
The expression is not evaluated.
-
When typeid is applied to a typeid, the result refers
to a type_info object representing the type of the typeid.
If
the type of the typeid is a reference type, the result of the
typeid
expression refers to a type_info object representing the
referenced type. If the type of the typeid is a class type
or a reference to a class type, the class shall be completely defined.
Types shall not be defined in the typeid.
-
The toplevel cvqualifiers of the lvalue expression or the
typeid
that
is the operand of typeid are always ignored. [Example:
class D { ... };
D d1;
const D d2;
typeid( d1) == typeid( d2); // yields
true
typeid( D) == typeid( const D); // yields
true
typeid( D) == typeid( d2); // yields
true
typeid( D) == typeid( const D&); // yields
true
--end example]
-
If the header <typeinfo> (18.5.1) is not included prior to
a use of typeid, the program is illformed.
-
[Note: 12.7 describes the behavior of typeid applied to
an object under construction or destruction. ]
5.2.9 Static cast
|
[expr.static.cast]
|
-
The result of the expression static_cast< T>( v) is the result
of converting the expression v to type T. If T
is
a reference type, the result is an lvalue; otherwise, the result is an
rvalue. Types shall not be defined in a static_cast. The
static_cast
operator
shall not cast away constness (5.2.11).
-
An expression e can be explicitly converted to a type T
using
a static_cast of the form static_cast< T>( e) if the
declaration "T t( e);"
is wellformed, for some invented temporary
variable t (8.5). The effect of such an explicit conversion is
the same as performing the declaration and initialization and then using
the temporary variable as the result of the conversion. The result is an
lvalue if T is a reference type (8.3.2), and an rvalue otherwise.
The expression e
is used as an lvalue if and only if the initialization
uses it as an lvalue.
-
Otherwise, the static_cast shall perform one of the conversions
listed below. No other conversion shall be performed explicitly using a
static_cast.
-
Any expression can be explicitly converted to type "cv void."
The
expression value is discarded. [Note: however, if the value is in a temporary
variable (12.2), the destructor for that variable is not executed until
the usual time, and the value of the variable is preserved for the purpose
of executing the destructor. ] The lvaluetorvalue (4.1), arraytopointer
(4.2), and functiontopointer (4.3) standard conversions are not
applied to the expression.
-
An lvalue of type "cv1 B", where B is a class type, can
be cast to type "reference to cv2 D", where D is
a class derived (clause 10) from B, if a valid standard conversion
from "pointer to D" to "pointer to B" exists (4.10),
cv2
is
the same cvqualification as, or greater cvqualification than,
cv1,
and B is not a virtual base class of D.
The result
is an lvalue of type "cv2 D." If the lvalue of type "cv1
B"
is
actually a subobject of an object of type
D, the lvalue refers
to the enclosing object of type D. Otherwise, the result of the
cast is undefined. [Example:
struct B {};
struct D : public B {};
D d;
B &br = d;
static_cast< D&>( br); // produces
lvalue to the original d object
--end example]
-
The inverse of any standard conversion sequence (clause 4), other than
the lvaluetorvalue (4.1), arraytopointer (4.2), functiontopointer
(4.3), and boolean (4.12) conversions, can be performed explicitly using
static_cast
subject
to the restriction that the explicit conversion does not cast away constness
(5.2.11), and the following additional rules for specific cases:
-
A value of integral type can be explicitly converted to an enumeration
type. The value is unchanged if the integral value is within the range
of the enumeration values (7.2). Otherwise, the resulting enumeration value
is unspecified.
-
An rvalue of type "pointer to cv1 B", where B
is
a class type, can be converted to an rvalue of type "pointer to cv2
D",
where
D
is a class derived (clause 10) from B,
if a valid standard
conversion from "pointer to D" to "pointer to
B" exists
(4.10), cv2 is the same cvqualification as, or greater cvqualification
than, cv1, and B is not a virtual base class of D.
The
null pointer value (4.10) is converted to the null pointer value of the
destination type. If the rvalue of type "pointer to cv1 B"points
to a B that is actually a subobject of an object of type
D,
the resulting pointer points to the enclosing object of type
D.
Otherwise, the result of the cast is undefined.
-
An rvalue of type "pointer to member of D of type cv1
T"
can
be converted to an rvalue of type "pointer to member of B of type
cv2
T",
where
B is a base class (clause 10) of
D,
if a valid standard
conversion from "pointer to member of B
of type T"
to
"pointer to member of D of type T"
exists (4.11), and
cv2 is the same cvqualification as, or greater cvqualification
than, cv1.
63) The null member pointer
value (4.11) is converted to the null member pointer value of the
destination type. If class
B
contains the original member, or
is a base or derived class of the class containing the original member,
the resulting pointer to member points to the original member. Otherwise,
the result of the cast is undefined. [Note: although class B
need
not contain the original member, the dynamic type of the object on which
the pointer to member is dereferenced must contain the original member;
see 5.5. ]
-
An rvalue of type "pointer to cv void" can be explicitly
converted to a pointer to object type. A value of type pointer to object
converted to "pointer to cv void"
and back to the original
pointer type will have its original value.
5.2.10 Reinterpret cast
|
[expr.reinterpret.cast]
|
-
The result of the expression reinterpret_cast< T>( v) is the
result of converting the expression v to type T. If
T
is
a reference type, the result is an lvalue; otherwise, the result is an
rvalue and the lvaluetorvalue (4.1), array topointer
(4.2), and functiontopointer (4.3) standard conversions are performed
on the the expression v. Types shall not be defined in a reinterpret_cast.
Conversions
that can be performed explicitly using reinterpret_cast
are
listed below. No other conversion can be performed explicitly using reinterpret_
cast.
-
The reinterpret_cast operator shall not cast away constness. [Note:
see 5.2.11 for the definition of '' casting away constness''. Subject to
the restrictions in this section, an expression may be cast to its own
type using a reinterpret_cast operator. ]
-
The mapping performed by reinterpret_cast is implementation
defined. [Note: it might, or might not, produce a representation
different from the original value. ]
-
A pointer can be explicitly converted to any integral type large enough
to hold it. The mapping function is implementationdefined [Note:
it is intended to be unsurprising to those who know the addressing structure
of the underlying machine. ]
-
A value of integral type or enumeration type can be explicitly converted
to a pointer. 64) 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; mappings
between pointers and integers are otherwise implementationdefined.
-
A pointer to a function can be explicitly converted to a pointer to a function
of a different type. The effect of calling a function through a pointer
to a function type (8.3.5) that is not the same as the type used in the
definition of the function is undefined. Except that converting an rvalue
of type "pointer to T1" to the type "pointer to T2"
(where
T1
and
T2 are function types) and back to its original type yields the
original value, the result of such a pointer conversion is
unspecified. [Note: see also 4.10 for more details of pointer conversions.
]
-
A pointer to an object can be explicitly converted to a pointer to an object
of different type. 65) Except that converting
an rvalue of type "pointer to T1" to the type "pointer to T2"
(where
T1
and
T2 are object types and where the alignment requirements
of T2
are no stricter than those of T1)
and back to its
original type yields the original pointer value, the result of such a pointer
conversion is unspecified.
-
The null pointer value (4.10) is converted to the null pointer value of
the destination type.
-
An rvalue of type "pointer to member of X of type T1"
can
be explicitly converted to an rvalue of type "pointer to member of Y
of
type T2" if T1 and
T2
are both function types
or both object types. 66) The null member
pointer value (4.11) is converted to the null member pointer value of the
destination type. The result of this conversion is unspecified, except
in the following cases:
-
converting an rvalue 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.
-
converting an rvalue 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.
-
An lvalue expression of type T1 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.
That
is, a reference cast reinterpret_cast< T&>( x) has the
same effect as the conversion *reinterpret_cast< T*>(& x)
with
the builtin
&
and
*
operators. The result is
an lvalue that refers to the same object as the source lvalue, but with
a different type. No temporary is created, no copy is made, and constructors
(12.1) or conversion functions (12.3) are not called. 67)
5.2.11 Const cast
|
[expr.const.cast]
|
-
The result of the expression const_cast< T>( v) is of type
T.
If
T is a reference type, the result is an lvalue; otherwise, the
result is an rvalue and, the lvaluetorvalue (4.1), arraytopointer
(4.2), and functiontopointer (4.3) standard conversions are performed
on the expression v. Types shall not be defined in a const_cast.
Conversions
that can be performed explicitly using const_cast
are listed below.
No other conversion shall be performed explicitly using const_cast.
-
[Note: Subject to the restrictions in this section, an expression
may be cast to its own type using a const_cast operator. ]
-
For two pointer types T1 and T2 where
T1 is cv1,0 pointer
to cvl,1 pointer to . . . cv1,n-1
pointer to cv1,n T
and
T2 is cv2,0 pointer
to cv2,1 pointer to . . . cv2,n-1
pointer to cv2,n T
where T is any object type or the void type and where
cv1,kand
cv2,kmay
be different cvqualifications, an rvalue of type
T1 may be
explicitly converted to the type
T2
using a
const_cast.
The
result of a pointer const_cast refers to the original object.
-
An lvalue of type T1 can be explicitly converted to an lvalue
of type T2 using the cast const_cast< T2&> (where
T1
and
T2
are object types) if a pointer to T1 can be explicitly converted
to the type pointer to T2 using a const_ cast. The result
of a reference const_cast refers to the original object.
-
For a const_cast involving pointers to data members, multilevel
pointers to data members and multilevel mixed pointers and pointers
to data members (4.4), the rules for const_cast are the same as
those used for pointers; the "member" aspect of a pointer to member is
ignored when determining where the cvqualifiers are added or removed
by the const_cast. The result of a pointer to data member const_cast
refers
to the same member as the original (uncast) pointer to data member.
-
A null pointer value (4.10) is converted to the null pointer value of the
destination type. The null member pointer value (4.11) is converted to
the null member pointer value of the destination type.
-
[Note: Depending on the type of the object, a write operation through
the pointer, lvalue or pointer to data member resulting from a
const_cast
that
casts away a constqualifier 68) may
produce undefined behavior (7.1.5.1). ]
-
The following rules define the process known as casting away constness.
In
these rules Tn and Xn represent types. For two pointer
types:
X1 is T1cv1,1*
.
. . cv1,N * where T1 is not
a pointer type
X2 is T2cv2,1
* . . . cv2,M * where T2 is not a pointer type
K is min( N, M)
casting from X1 to X2 casts away constness if, for
a nonpointer type T there does not exist an implicit conversion
(clause 4) from:
Tcv1,(N-K+1)*
cv1,(N-K+2) * . . .
cv1,
N
*
to
Tcv2,(M-K+1)*
cv2,(M-K+2) * . . .
cv2,M
*
-
Casting from an lvalue of type T1 to an lvalue of type T2
using
a reference cast casts away constness if a cast from an rvalue of type
"pointer to T1" to the type "pointer to T2" casts away
constness.
-
Casting from an rvalue of type "pointer to data member of X of
type T1" to the type "pointer to data member of Y of
type T2" casts away constness if a cast from an rvalue of type
"pointer to T1" to the type"pointer to T2" casts away
constness.
-
For multilevel pointer to members and multilevel mixed pointers
and pointer to members (4.4), the"member" aspect of a pointer to member
level is ignored when determining if a const cv qualifier
has been cast away.
-
[Note: some conversions which involve only changes in cv qualification
cannot be done using const_cast. For instance, conversions between
pointers to functions are not covered because such conversions lead to
values whose use causes undefined behavior. For the same reasons, conversions
between pointers to member functions, and in particular, the conversion
from a pointer to a const member function to a pointer to a nonconst
member function, are not covered. ]
53)
The precedence of operators is not directly specified, but it can be derived from the syntax.
54)
As a consequence, operands of type bool, wchar_t, or an enumerated type are converted to some integral type.
55)
The cast and assignment operators must still perform their specific conversions as described in 5.4, 5.2.9 and 5.17.
56) This is true even if the subscript operator is used in the following common idiom: &x[0].
57)
A static member function (9.4) is an ordinary function.
58)
This evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the idexpression denotes a static member.
59)
Note that if E1 has the type "pointer to class X", then (*(E1))is an lvalue.
60)
The most derived object (1.8) pointed or referred to by v can contain other B objects as base classes, but these are ignored.
61)
The recommended name for such a class is extended_type_info.
62)
If p is an expression of pointer type, then *p, (* p), *( p), ((* p)), *(( p)), and so on all meet this requirement.
63)
Function types (including those used in pointer to member function types) are never cvqualified; see 8.3.5 .
64)
Converting an integral constant expression (5.19) with value zero always yields a null pointer (4.10), but converting other expressions that happen to have value zero need not yield a null pointer.
65)
The types may have different cvqualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness.
66)
T1 and T2may have different cvqualifiers, subject to the overall restriction that a cannot cast away constness.
67)
This is sometimes referred to as a type pun.
68)
const_cast is not limited to conversions that cast away a constqualifier.