______________________________________________________________________
5 Expressions [expr]
______________________________________________________________________
1 [Note: Clause _expr_ 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.
2 Operators can be overloaded, that is, given meaning when applied to
expressions of class type (clause _class_) or enumeration type
(_dcl.enum_). Uses of overloaded operators are transformed into func-
tion calls as described in _over.oper_. Overloaded operators obey the
rules for syntax specified in clause _expr_, 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 (_over.oper_), and
are not guaranteed for operands of type bool. --end note]
3 Clause _expr_ 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 built-in operators, that is, for opera-
tors applied to types for which they are defined by this Standard.
However, these built-in operators participate in overload resolution,
and as part of that process user-defined conversions will be consid-
ered where necessary to convert the operands to types appropriate for
the built-in operator. If a built-in operator is selected, such con-
versions will be applied to the operands before the operation is con-
sidered further according to the rules in clause _expr_; see
_over.match.oper_, _over.built_.
4 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.1) Between the previ-
ous and next sequence point a scalar object shall have its stored
value modified at most once by the evaluation of an expression. Fur-
thermore, 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 expres-
sion; otherwise the behavior is undefined. [Example:
_________________________
1) The precedence of operators is not directly specified, but it can
be derived from the syntax.
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]
5 If during the evaluation of an expression, the result is not mathemat-
ically defined or not in the range of representable values for its
type, the behavior is undefined, unless such an expression is a con-
stant expression (_expr.const_), in which case the program is ill-
formed. [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. ]
6 If an expression initially has the type "reference to T" (_dcl.ref_,
_dcl.init.ref_), the type is adjusted to T" prior to any further anal-
ysis, the expression designates the object or function denoted by the
reference, and the expression is an lvalue.
7 An expression designating an object is called an object-expression.
8 Whenever an lvalue expression appears as an operand of an operator
that expects an rvalue for that operand, the lvalue-to-rvalue
(_conv.lval_), array-to-pointer (_conv.array_), or function-to-pointer
(_conv.func_) standard conversions are applied to convert the expres-
sion to an rvalue. [Note: because cv-qualifiers are removed from the
type of an expression of non-class type when the expression is con-
verted to an rvalue, an lvalue expression of type const int can, for
example, be used where an rvalue expression of type int is required.
]
9 Many binary operators that expect operands of arithmetic or enumera-
tion 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 con-
verted 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 (_conv.prom_) shall be performed
on both operands.2)
_________________________
2) As a consequence, operands of type bool, wchar_t, or an enumerated
type are converted to some integral type.
--Then, if either operand is unsigned long the other shall be con-
verted 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 con-
verted to unsigned.
[Note: otherwise, the only remaining case is that both operands are
int ]
10The 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.3)
5.1 Primary expressions [expr.prim]
1 Primary expressions are literals, names, and names qualified by the
scope resolution operator ::.
primary-expression:
literal
this
( expression )
id-expression
id-expression:
unqualified-id
qualified-id
unqualified-id:
identifier
operator-function-id
conversion-function-id
~ class-name
template-id
2 A literal is a primary expression. Its type depends on its form
(_lex.literal_). A string literal is an lvalue; all other literals
are rvalues.
3 The keyword this names a pointer to the object for which a nonstatic
member function (_class.this_) is invoked. The keyword this shall be
used only inside a nonstatic class member function body (_class.mfct_)
_________________________
3) The cast and assignment operators must still perform their specific
conversions as described in _expr.cast_, _expr.static.cast_ and _ex-
pr.ass_.
or in a constructor mem-initializer (_class.base.init_). The type of
the expression is a pointer to the function's class (_class.this_),
possibly with cv-qualifiers on the class type. The expression is an
rvalue.
4 The operator :: followed by an identifier, a qualified-id, or an oper-
ator-function-id is a primary-expression. Its type is specified by
the declaration of the identifier, qualified-id, or operator-function-
id. The result is the entity denoted by the identifier, qualified-id,
or operator-function-id. The result is an lvalue if the entity is a
function or variable. The identifier, qualified-id, or operator-func-
tion-id shall have global namespace scope or be visible in global
scope because of a using-directive (_namespace.udir_). [Note: the use
of :: allows a type, an object, a function, an enumerator, or a names-
pace declared in the global namespace to be referred to even if its
identifier has been hidden (_basic.lookup.qual_). ]
5 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.
6 An id-expression is a restricted form of a primary-expression. [Note:
an id-expression can appear after . and -> operators (_expr.ref_). ]
7 An identifier is an id-expression provided it has been suitably
declared (clause _dcl.dcl_). [Note: for operator-function-ids, see
_over.oper_; for conversion-function-ids, see _class.conv.fct_; for
template-ids, see _temp.names_. A class-name prefixed by ~ denotes a
destructor; see _class.dtor_. Within the definition of a nonstatic
member function, an identifier that names a nonstatic member is trans-
formed to a class member access expression (_class.mfct.nonstatic_).
] 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.
8 qualified-id:
::opt nested-name-specifier templateopt unqualified-id
:: identifier
:: operator-function-id
:: template-id
nested-name-specifier:
class-or-namespace-name :: nested-name-specifieropt
class-or-namespace-name :: template nested-name-specifier
class-or-namespace-name:
class-name
namespace-name
A nested-name-specifier that names a class, optionally followed by the
keyword template (_temp.arg.explicit_), and then followed by the name
of a member of either that class (_class.mem_) or one of its base
classes (clause _class.derived_), is a qualified-id; _class.qual_
describes name lookup for class members that appear in qualified-ids.
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 qualified-id at any point in its potential scope
(_basic.scope.class_). ] Where class-name :: class-name is used, and
the two class-names refer to the same class, this notation names the
constructor (_class.ctor_). Where class-name :: ~ class-name is used,
the two class-names shall refer to the same class; this notation names
the destructor (_class.dtor_). [Note: a typedef-name that names a
class is a class-name (_dcl.typedef_). Except as the identifier in
the declarator for a constructor or destructor definition outside of a
class member-specification (_class.ctor_, _class.dtor_), a typedef-
name that names a class may be used in a qualified-id to refer to a
constructor or destructor. ]
9 A nested-name-specifier that names a namespace (_basic.namespace_),
followed by the name of a member of that namespace (or the name of a
member of a namespace made visible by a using-directive ) is a quali-
fied-id; _namespace.qual_ describes name lookup for namespace members
that appear in qualified-ids. 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.
10In a qualified-id, if the id-expression is a conversion-function-id,
its conversion-type-id shall denote the same type in both the context
in which the entire qualified-id occurs and in the context of the
class denoted by the nested-name-specifier.
11An id-expression that denotes a nonstatic data member or nonstatic
member function of a class can only be used:
--as part of a class member access (_expr.ref_) in which the object-
expression refers to the member's class or a class derived from that
class, or
--to form a pointer to member (_expr.unary.op_), or
--in the body of a nonstatic member function of that class or of a
class derived from that class (_class.mfct.nonstatic_), or
--in a mem-initializer for a constructor for that class or for a class
derived from that class (_class.base.init_).
12A template-id shall be used as an unqualified-id only as specified in
_temp.explicit_, _temp.spec_, and _temp.class.spec_.
5.2 Postfix expressions [expr.post]
1 Postfix expressions group left-to-right.
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-listopt )
simple-type-specifier ( expression-listopt )
typename ::opt nested-name-specifier identifier ( expression-listopt )
typename ::opt nested-name-specifier templateopt template-id ( expression-listopt )
postfix-expression . templateopt id-expression
postfix-expression -> templateopt id-expression
postfix-expression . pseudo-destructor-name
postfix-expression -> pseudo-destructor-name
postfix-expression ++
postfix-expression --
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
const_cast < type-id > ( expression )
typeid ( expression )
typeid ( type-id )
expression-list:
assignment-expression
expression-list , assignment-expression
pseudo-destructor-name:
::opt nested-name-specifieropt type-name :: ~ type-name
::opt nested-name-specifier template template-id :: ~ type-name
::opt nested-name-specifieropt ~ type-name
5.2.1 Subscripting [expr.sub]
1 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 com-
pletely-defined object type.4) The expression E1[E2] is identical (by
definition) to *((E1)+(E2)). [Note: see _expr.unary_ and _expr.add_
for details of * and + and _dcl.array_ for details of arrays. ]
5.2.2 Function call [expr.call]
1 There are two kinds of function call: ordinary function call and mem-
ber function5) (_class.mfct_) call. A function call is a postfix
expression followed by parentheses containing a possibly empty, comma-
separated 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 func-
tion-to-pointer standard conversion (_conv.func_) is suppressed on the
postfix expression), or it shall have pointer to function type. Call-
ing a function through an expression whose function type has a lan-
guage linkage that is different from the language linkage of the
_________________________
4) This is true even if the subscript operator is used in the follow-
ing common idiom: &x[0].
5) A static member function (_class.static_) is an ordinary function.
function type of the called function's definition is undefined
(_dcl.link_). For a member function call, the postfix expression
shall be an implicit (_class.mfct.nonstatic_, _class.static_) or
explicit class member access (_expr.ref_) whose id-expression is a
function member name, or a pointer-to-member expression
(_expr.mptr.oper_) 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 _class.mfct.nonstatic_). ] If a
function or member function name is used, the name can be overloaded
(clause _over_), in which case the appropriate function shall be
selected according to the rules in _over.match_. The function called
in a member function call is normally selected according to the static
type of the object expression (clause _class.derived_), but if that
function is virtual and is not specified using a qualified-id then the
function actually called will be the final overrider (_class.virtual_)
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. _class.cdtor_
describes the behavior of virtual function calls when the object-
expression refers to an object under construction or destruction. ]
2 If no declaration of the called function is visible from the scope of
the call the program is ill-formed.
3 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.
4 When a function is called, each parameter (_dcl.fct_) shall be ini-
tialized (_dcl.init_, _class.copy_, _class.ctor_) with its correspond-
ing argument. When a function is called, the parameters that have
object type shall have completely-defined object type. [Note: this
still allows a parameter to be a pointer or reference to an incomplete
class type. However, it prevents a passed-by-value 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 con-
struction of temporaries with the initialization of the parameter (see
_class.temporary_). The lifetime of a parameter ends when the func-
tion in which it is defined returns. The initialization and destruc-
tion of each parameter occurs within the context of the calling func-
tion. [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 function-try-
block (clause _except_) with a handler that could handle the excep-
tion, this handler is not considered. ] The value of a function call
is the value returned by the called function except in a virtual func-
tion 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 stati-
cally chosen function.
5 [Note: 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_); if the reference
is to a const-qualified 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 (_dcl.type_, _lex.literal_, _lex.string_,
_dcl.array_, _class.temporary_). In addition, it is possible to mod-
ify the values of nonconstant objects through pointer parameters. ]
6 A function can be declared to accept fewer arguments (by declaring
default arguments (_dcl.fct.default_)) or more arguments (by using the
ellipsis, ... _dcl.fct_) than the number of parameters in the func-
tion definition (_dcl.fct.def_). [Note: this implies that, except
where the ellipsis ...) is used, a parameter is available for each
argument. ]
7 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 (_lib.support.runtime_). The
lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_), and
function-to-pointer (_conv.func_) 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 ill-formed. If the argument has a non-POD
class type (clause _class_), the behavior is undefined. If the argu-
ment has integral or enumeration type that is subject to the integral
promotions (_conv.prom_), or a floating point type that is subject to
the floating point promotion (_conv.fpprom_), the value of the argu-
ment is converted to the promoted type before the call. These promo-
tions are referred to as the default argument promotions.
8 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.
9 Recursive calls are permitted, except to the function named main
(_basic.start.main_).
10A function call is an lvalue if and only if the result type is a ref-
erence.
5.2.3 Explicit type conversion (functional [expr.type.conv]
notation)
1 A simple-type-specifier (_dcl.type_) 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
(_expr.cast_). If the simple-type-specifier 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 (_dcl.init_, _class.ctor_), 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.
2 The expression T(), where T is a simple-type-specifier (_dcl.type.sim-
ple_) for a non-array complete object type or the (possibly cv-quali-
fied) void type, creates an rvalue of the specified type, whose value
is determined by default-initialization (_dcl.init_; no initialization
is done for the void() case). [Note: if T is a non-class type that is
cv-qualified, the cv-qualifiers are ignored when determining the type
of the resulting rvalue (_basic.lval_). ]
5.2.4 Pseudo destructor call [expr.pseudo]
1 The use of a pseudo-destructor-name after a dot . or arrow -> opera-
tor represents the destructor for the non-class type named by type-
name. 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 postfix-expression before the dot
or arrow.
2 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 pseudo-destructor-name shall be the same as the object type. Fur-
thermore, the two type-names in a pseudo-destructor-name of the form
::opt nested-name-specifieropt type-name :: ~ type-name
shall designate the same scalar type. The cv-unqualified versions of
the object type and of the type designated by the pseudo-destructor-
name shall be the same type.
5.2.5 Class member access [expr.ref]
1 A postfix expression followed by a dot . or an arrow ->, optionally
followed by the keyword template (_temp.arg.explicit_), and then fol-
lowed by an id-expression, is a postfix expression. The postfix
expression before the dot or arrow is evaluated;6) the result of that
evaluation, together with the id-expression, determine the result of
the entire postfix expression.
2 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
_________________________
6) This evaluation happens even if the result is unnecessary to deter-
mine the value of the entire postfix expression, for example if the
id-expression denotes a static member.
type). In these cases, the id-expression 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 _class_), the name of a
class is also considered a nested member of that class. ] [Note:
_basic.lookup.classref_ describes how names are looked up after the .
and -> operators. ]
3 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
_expr.ref_ will address only the first option (dot)7). Abbreviating
object-expression.id-expression as E1.E2, then the type and lvalue
properties of this expression are determined as follows. In the
remainder of _expr.ref_, cq represents either const or the absence of
const; vq represents either volatile or the absence of volatile. cv
represents an arbitrary set of cv-qualifiers, as defined in
_basic.type.qualifier_.
4 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 non-static 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 mem-
ber, 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 (_over.match_) is used to determine whether E1.E2 refers
to a static or a non-static 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 non-static 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 non-
static member function. The expression can be used only as the
_________________________
7) Note that if E1 has the type "pointer to class X", then (*(E1)) is
an lvalue.
left-hand operand of a member function call (_class.mfct_).
[Note: any redundant set of parentheses surrounding the expression
is ignored (_expr.prim_). ] 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 expres-
sion E1.E2 is not an lvalue. The type of E1.E2 is T.
5 [Note: "class objects" can be structures (_class.mem_) and unions
(_class.union_). Classes are discussed in clause _class_. ]
5.2.6 Increment and decrement [expr.post.incr]
1 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 _depr_. ] The result is an rvalue. The type of
the result is the cv-unqualified version of the type of the operand.
See also _expr.add_ and _expr.ass_.
2 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 _expr.pre.incr_. ]
5.2.7 Dynamic cast [expr.dynamic.cast]
1 The result of the expression dynamic_cast<T>(v) is the result of con-
verting 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 (_expr.const.cast_).
2 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 refer-
ence type, v shall be an lvalue of a complete class type, and the
result is an lvalue of the type referred to by T.
3 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 cv-qualified than
the class object type in v, the result is v (converted if necessary).
4 If the value of v is a null pointer value in the pointer case, the
result is the null pointer value of type R.
5 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 unique8) B sub-object of the D object
referred to by v. In both the pointer and reference cases, cv1 shall
be the same cv-qualification as, or greater cv-qualification than,
cv2, and B shall be an accessible unambiguous base class of D. [Exam-
ple:
struct B {};
struct D : B {};
void foo(D* dp)
{
B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}
--end example]
6 Otherwise, v shall be a pointer to or an lvalue of a polymorphic type
(_class.virtual_).
7 If T is "pointer to cv void," then the result is a pointer to the most
derived object pointed to by v. Otherwise, a run-time check is
applied to see if the object pointed or referred to by v can be con-
verted to the type pointed or referred to by T.
8 The run-time check logically executes as follows:
--If, in the most derived object pointed (referred) to by v, v points
(refers) to a public base class sub-object 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 sub-object 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 sub-object of the most derived
object.
--Otherwise, the run-time check fails.
9 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 (_lib.bad.cast_). [Example:
_________________________
8) The most derived object (_intro.object_) pointed or referred to by
v can contain other B objects as base classes, but these are ignored.
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 sub-objects
E* ep = (E*)ap; // ill-formed:
// cast from virtual base
E* ep1 = dynamic_cast<E*>(ap); // succeeds
}
--end example] [Note: _class.cdtor_ describes the behavior of a
dynamic_cast applied to an object under construction or destruction.
]
5.2.8 Type identification [expr.typeid]
1 The result of a typeid expression is an lvalue of static type const
std::type_info (_lib.type.info_) and dynamic type const std::type_info
or const name where name is an implementation-defined class derived
from std::type_info which preserves the behavior described in
_lib.type.info_.9) The lifetime of the object referred to by the
lvalue extends to the end of the program. Whether or not the destruc-
tor is called for the type_info object at the end of the program is
unspecified.
2 When typeid is applied to an lvalue expression whose type is a poly-
morphic class type (_class.virtual_), the result refers to a type_info
object representing the type of the most derived object
(_intro.object_) (that is, the dynamic type) to which the lvalue
refers. If the lvalue expression is obtained by applying the unary *
operator to a pointer10) and the pointer is a null pointer value
(_conv.ptr_), the typeid expression throws the bad_typeid exception
(_lib.bad.typeid_).
_________________________
9) The recommended name for such a class is extended_type_info.
10) If p is an expression of pointer type, then *p, (*p), *(p),
((*p)), *((p)), and so on all meet this requirement.
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 repre-
senting the static type of the expression. Lvalue-to-rvalue
(_conv.lval_), array-to-pointer (_conv.array_), and function-to-
pointer (_conv.func_) conversions are not applied to the expression.
If the type of the expression is a class type, the class shall be com-
pletely-defined. The expression is not evaluated.
4 When typeid is applied to a type-id, the result refers to a type_info
object representing the type of the type-id. If the type of the type-
id 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 type-id is a class type or a reference to a class type, the class
shall be completely-defined. Types shall not be defined in the type-
id.
5 The top-level cv-qualifiers of the lvalue expression or the type-id
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]
6 If the header <typeinfo> (_lib.type.info_) is not included prior to a
use of typeid, the program is ill-formed.
7 [Note: _class.cdtor_ describes the behavior of typeid applied to an
object under construction or destruction. ]
5.2.9 Static cast [expr.static.cast]
1 The result of the expression static_cast<T>(v) is the result of con-
verting 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 (_expr.const.cast_).
2 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 well-formed, for some invented temporary variable t (_dcl.init_).
The effect of such an explicit conversion is the same as performing
the declaration and initialization and then using the temporary vari-
able as the result of the conversion. The result is an lvalue if T is
a reference type (_dcl.ref_), and an rvalue otherwise. The expression
e is used as an lvalue if and only if the initialization uses it as an
lvalue.
3 Otherwise, the static_cast shall perform one of the conversions listed
below. No other conversion shall be performed explicitly using a
static_cast.
4 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 (_class.temporary_), the destructor for that vari-
able is not executed until the usual time, and the value of the vari-
able is preserved for the purpose of executing the destructor. ] The
lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_), and
function-to-pointer (_conv.func_) standard conversions are not applied
to the expression.
5 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
_class.derived_) from B, if a valid standard conversion from "pointer
to D" to "pointer to B" exists (_conv.ptr_), cv2 is the same cv-quali-
fication as, or greater cv-qualification 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 sub-object of an object of
type D, the lvalue refers to the enclosing object of type D. Other-
wise, 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]
6 The inverse of any standard conversion sequence (clause _conv_), other
than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
(_conv.array_), function-to-pointer (_conv.func_), and boolean
(_conv.bool_) conversions, can be performed explicitly using
static_cast subject to the restriction that the explicit conversion
does not cast away constness (_expr.const.cast_), and the following
additional rules for specific cases:
7 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 (_dcl.enum_). Otherwise, the result-
ing enumeration value is unspecified.
8 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 _class.derived_) from B, if a valid standard conver-
sion from "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is
the same cv-qualification as, or greater cv-qualification than, cv1,
and B is not a virtual base class of D. The null pointer value
(_conv.ptr_) 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 sub-object 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.
9 An rvalue of type "pointer to member of D of type cv1 T" can be con-
verted to an rvalue of type "pointer to member of B of type cv2 T",
where B is a base class (clause _class.derived_) 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 (_conv.mem_), and cv2 is the
same cv-qualification as, or greater cv-qualification than, cv1.11)
The null member pointer value (_conv.mem_) 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 derefer-
enced must contain the original member; see _expr.mptr.oper_. ]
10An 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]
1 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
lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_), and
function-to-pointer (_conv.func_) standard conversions are performed
on the the expression v. Types shall not be defined in a reinter-
pret_cast. Conversions that can be performed explicitly using rein-
terpret_cast are listed below. No other conversion can be performed
explicitly using reinterpret_cast.
2 The reinterpret_cast operator shall not cast away constness. [Note:
see _expr.const.cast_ for the definition of ``casting away const-
ness''. Subject to the restrictions in this section, an expression
may be cast to its own type using a reinterpret_cast operator. ]
3 The mapping performed by reinterpret_cast is implementation-defined.
[Note: it might, or might not, produce a representation different from
the original value. ]
4 A pointer can be explicitly converted to any integral type large
enough to hold it. The mapping function is implementation-defined
[Note: it is intended to be unsurprising to those who know the
addressing structure of the underlying machine. ]
5 A value of integral type or enumeration type can be explicitly con-
verted to a pointer.12) A pointer converted to an integer of suffi-
cient size (if any such exists on the implementation) and back to the
_________________________
11) Function types (including those used in pointer to member function
types) are never cv-qualified; see _dcl.fct_ .
12) Converting an integral constant expression (_expr.const_) with
value zero always yields a null pointer (_conv.ptr_), but converting
other expressions that happen to have value zero need not yield a null
pointer.
same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined.
6 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 (_dcl.fct_) 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 pointer value, the result of such a
pointer conversion is unspecified. [Note: see also _conv.ptr_ for
more details of pointer conversions. ]
7 A pointer to an object can be explicitly converted to a pointer to an
object of different type.13) 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.
8 The null pointer value (_conv.ptr_) is converted to the null pointer
value of the destination type.
9 An rvalue of type "pointer to member of X of type T1" can be explic-
itly 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.14) The
null member pointer value (_conv.mem_) 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 dif-
ferent 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.
10An 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 con-
verted 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 built-in & and * opera-
tors. 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
_________________________
13) The types may have different cv-qualifiers, subject to the overall
restriction that a reinterpret_cast cannot cast away constness.
14) T1 and T2 may have different cv-qualifiers, subject to the overall
restriction that a reinterpret_cast cannot cast away constness.
copy is made, and constructors (_class.ctor_) or conversion functions
(_class.conv_) are not called.15)
5.2.11 Const cast [expr.const.cast]
1 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 lvalue-to-rvalue (_conv.lval_), array-to-pointer
(_conv.array_), and function-to-pointer (_conv.func_) standard conver-
sions 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.
2 [Note: Subject to the restrictions in this section, an expression may
be cast to its own type using a const_cast operator. ]
3 For two pointer types T1 and T2 where
0sfont]I]ize]u'TR]1R]is2]cvR]1R],pRo]i0nter to2]cvR]1R],pRo]i1nter to2]R].R].R].cvR]1R],Rn]Rp]o[imnit]eRr]1to2]cvR]1RT]0,rnfont]
and
0sfont]I]ize]u'TR]2R]is2]cvR]2R],pRo]i0nter to2]cvR]2R],pRo]i1nter to2]R].R].R].cvR]2R],Rn]Rp]o[imnit]eRr]1to2]cvR]2RT]0,rnfont]
where T is any object type or the void type and where cv1,k and cv2,k
may be different cv-qualifications, 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.
4 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.
5 For a const_cast involving pointers to data members, multi-level
pointers to data members and multi-level mixed pointers and pointers
to data members (_conv.qual_), 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 cv-qualifiers 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.
6 A null pointer value (_conv.ptr_) is converted to the null pointer
value of the destination type. The null member pointer value
(_conv.mem_) is converted to the null member pointer value of the des-
tination type.
7 [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 const-qualifier16) may produce undefined
_________________________
15) This is sometimes referred to as a type pun.
behavior (_dcl.type.cv_). ]
8 The following rules define the process known as casting away const-
ness. In these rules Tn and Xn represent types. For two pointer
types:
0sfont]I]ize]u'CW]XCW]12]R]is2]CW]TCW]12]cvR]1R],*R]1.R].R].cvR]1R],*NR]whereTR]1isnotapointertype2]0rfont]
0sfont]I]ize]u'CW]XCW]22]R]is2]CW]TCW]22]cvR]2R],*R]1.R].R].cvR]2R],*MR]whereTR]2isnotapointertype2]0rfont]
0sfont]I]ize]u'KR]is2]minR](NR],MR])0rfont]
casting from X1 to X2 casts away constness if, for a non-pointer type
T there does not exist an implicit conversion (clause _conv_) from:
0sfont]I]ize]u'TcvR]1R],R](NRR]]*[cmviR]K1R][,pRl]](R]*R].]RK]R.]R[]p.lc]vR]21R]*N0rfont]
to
0sfont]I]ize]u'TcvR]2R],R](MRR]]*[cmviR]K2R][,pRl]](R]*R].]RK]R.]R[]p.lc]vR]2R]*M0rfont]
9 Casting from an lvalue of type T1 to an lvalue of type T2 using a ref-
erence cast casts away constness if a cast from an rvalue of type
"pointer to T1" to the type "pointer to T2" casts away constness.
10Casting 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.
11For multi-level pointer to members and multi-level mixed pointers and
pointer to members (_conv.qual_), the "member" aspect of a pointer to
member level is ignored when determining if a const cv-qualifier has
been cast away.
12[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 non-const member function, are not covered. ]
5.3 Unary expressions [expr.unary]
1 Expressions with unary operators group right-to-left.
_________________________
16) const_cast is not limited to conversions that cast away a const-
qualifier.
unary-expression:
postfix-expression
++ cast-expression
-- cast-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-id )
new-expression
delete-expression
unary-operator: one of
* & + - ! ~
5.3.1 Unary operators [expr.unary.op]
1 The unary * operator performs indirection: the expression to which it
is applied shall be a pointer to an object type, or a pointer to a
function type and the result is an lvalue referring to the object or
function to which the expression points. If the type of the expres-
sion is "pointer to T," the type of the result is "T." [Note: a
pointer to an incomplete type (other than cv void ) can be derefer-
enced. The lvalue thus obtained can be used in limited ways (to ini-
tialize a reference, for example); this lvalue must not be converted
to an rvalue, see _conv.lval_. ]
2 The result of the unary & operator is a pointer to its operand. The
operand shall be an lvalue or a qualified-id. In the first case, if
the type of the expression is "T," the type of the result is "pointer
to T." In particular, the address of an object of type "cv T" is
"pointer to cv T," with the same cv-qualifiers. For a qualified-id,
if the member is a static member of type "T", the type of the result
is plain "pointer to T." If the member is a nonstatic member of class
C of type T, the type of the result is "pointer to member of class C
of type T." [Example:
struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*
--end example] [Note: a pointer to member formed from a mutable non-
static data member (_dcl.stc_) does not reflect the mutable specifier
associated with the nonstatic data member. ]
3 A pointer to member is only formed when an explicit & is used and its
operand is a qualified-id not enclosed in parentheses. [Note: that
is, the expression &(qualified-id), where the qualified-id is enclosed
in parentheses, does not form an expression of type "pointer to mem-
ber." Neither does qualified-id, because there is no implicit conver-
sion from a qualified-id for a nonstatic member function to the type
"pointer to member function" as there is from an lvalue of function
type to the type "pointer to function" (_conv.func_). Nor is &unqual-
ified-id a pointer to member, even within the scope of the unquali-
fied-id's class. ]
4 The address of an object of incomplete type can be taken, but if the
complete type of that object is a class type that declares operator&()
as a member function, then the behavior is undefined (and no
diagnostic is required). The operand of & shall not be a bit-field.
5 The address of an overloaded function (clause _over_) can be taken
only in a context that uniquely determines which version of the over-
loaded function is referred to (see _over.over_). [Note: since the
context might determine whether the operand is a static or nonstatic
member function, the context can also affect whether the expression
has type "pointer to function" or "pointer to member function." ]
6 The operand of the unary + operator shall have arithmetic, enumera-
tion, or pointer type and the result is the value of the argument.
Integral promotion is performed on integral or enumeration operands.
The type of the result is the type of the promoted operand.
7 The operand of the unary - operator shall have arithmetic or enumera-
tion type and the result is the negation of its operand. Integral
promotion is performed on integral or enumeration operands. The nega-
tive of an unsigned quantity is computed by subtracting its value from
2n, where n is the number of bits in the promoted operand. The type
of the result is the type of the promoted operand.
8 The operand of the logical negation operator ! is implicitly con-
verted to bool (clause _conv_); its value is true if the converted
operand is false and false otherwise. The type of the result is bool.
9 The operand of ~ shall have integral or enumeration type; the result
is the one's complement of its operand. Integral promotions are per-
formed. The type of the result is the type of the promoted operand.
There is an ambiguity in the unary-expression ~X(), where X is a
class-name. The ambiguity is resolved in favor of treating ~ as a
unary complement rather than treating ~X as referring to a destructor.
5.3.2 Increment and decrement [expr.pre.incr]
1 The operand of prefix ++ is modified by adding 1, or set to true if it
is bool (this use is deprecated). The operand shall be a modifiable
lvalue. The type of the operand shall be an arithmetic type or a
pointer to a completely-defined object type. The value is the new
value of the operand; it is an lvalue. If x is not of type bool, the
expression ++x is equivalent to x+=1. [Note: see the discussions of
addition (_expr.add_) and assignment operators (_expr.ass_) for infor-
mation on conversions. ]
2 The operand of prefix -- is modified by subtracting 1. The operand
shall not be of type bool. The requirements on the operand of prefix
-- and the properties of its result are otherwise the same as those of
prefix ++. [Note: For postfix increment and decrement, see
_expr.post.incr_. ]
5.3.3 Sizeof [expr.sizeof]
1 The sizeof operator yields the number of bytes in the object represen-
tation of its operand. The operand is either an expression, which is
not evaluated, or a parenthesized type-id. The sizeof operator shall
not be applied to an expression that has function or incomplete type,
or to an enumeration type before all its enumerators have been
declared, or to the parenthesized name of such types, or to an lvalue
that designates a bit-field. sizeof(char), sizeof(signed char) and
sizeof(unsigned char) are 1; the result of sizeof applied to any other
fundamental type (_basic.fundamental_) is implementation-defined.
[Note: in particular, sizeof(bool) and sizeof(wchar_t) are
implementation-defined.17) ] [Note: See _intro.memory_ for the defini-
tion of byte and _basic.types_ for the definition of object represen-
tation. ]
2 When applied to a reference or a reference type, the result is the
size of the referenced type. When applied to a class, the result is
the number of bytes in an object of that class including any padding
required for placing objects of that type in an array. The size of a
most derived class shall be greater than zero (_intro.object_). The
result of applying sizeof to a base class subobject is the size of the
base class type.18) When applied to an array, the result is the total
number of bytes in the array. This implies that the size of an array
of n elements is n times the size of an element.
3 The sizeof operator can be applied to a pointer to a function, but
shall not be applied directly to a function.
4 The lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_),
and function-to-pointer (_conv.func_) standard conversions are not
applied to the operand of sizeof.
5 Types shall not be defined in a sizeof expression.
6 The result is a constant of type size_t. [Note: size_t is defined in
the standard header <cstddef>(_lib.support.types_). ]
5.3.4 New [expr.new]
1 The new-expression attempts to create an object of the type-id
(_dcl.name_) or new-type-id to which it is applied. The type of that
object is the allocated type. This type shall be a complete object
type, but not an abstract class type or array thereof (_intro.object_,
_basic.types_, _class.abstract_). [Note: because references are not
objects, references cannot be created by new-expressions. ] [Note:
the type-id may be a cv-qualified type, in which case the object cre-
ated by the new-expression has a cv-qualified type. ]
new-expression:
::opt new new-placementopt new-type-id new-initializeropt
::opt new new-placementopt ( type-id ) new-initializeropt
new-placement:
( expression-list )
_________________________
17) sizeof(bool) is not required to be 1.
18) The actual size of a base class subobject may be less than the re-
sult of applying sizeof to the subobject, due to virtual base classes
and less strict padding requirements on base class subobjects.
new-type-id:
type-specifier-seq new-declaratoropt
new-declarator:
ptr-operator new-declaratoropt
direct-new-declarator
direct-new-declarator:
[ expression ]
direct-new-declarator [ constant-expression ]
new-initializer:
( expression-listopt )
Entities created by a new-expression have dynamic storage duration
(_basic.stc.dynamic_). [Note: the lifetime of such an entity is not
necessarily restricted to the scope in which it is created. ] If the
entity is a non-array object, the new-expression returns a pointer to
the object created. If it is an array, the new-expression returns a
pointer to the initial element of the array.
2 The new-type-id in a new-expression is the longest possible sequence
of new-declarators. [Note: this prevents ambiguities between declara-
tor operators &, *, [], and their expression counterparts. ] [Exam-
ple:
new int * i; // syntax error: parsed as (new int*) i
// not as (new int)*i
The * is the pointer declarator and not the multiplication operator.
]
3 [Note: parentheses in a new-type-id of a new-expression can have sur-
prising effects. [Example:
new int(*[10])(); // error
is ill-formed because the binding is
(new int) (*[10])(); // error
Instead, the explicitly parenthesized version of the new operator can
be used to create objects of compound types (_basic.compound_):
new (int (*[10])());
allocates an array of 10 pointers to functions (taking no argument and
returning int). ] ]
4 The type-specifier-seq shall not contain class declarations, or enu-
meration declarations.
5 When the allocated object is an array (that is, the direct-new-
declarator syntax is used or the new-type-id or type-id denotes an
array type), the new-expression yields a pointer to the initial ele-
ment (if any) of the array. [Note: both new int and new int[10] have
type int* and the type of new int[i][10] is int (*)[10]. ]
6 Every constant-expression in a direct-new-declarator shall be an inte-
gral constant expression (_expr.const_) and evaluate to a strictly
positive value. The expression in a direct-new-declarator shall have
integral type (_basic.fundamental_) with a non-negative value. [Exam-
ple: if n is a variable of type int, then new float[n][5] is well-
formed (because n is the expression of a direct-new-declarator), but
new float[5][n] is ill-formed (because n is not a constant-expres-
sion). If n is negative, the effect of new float[n][5] is undefined.
]
7 When the value of the expression in a direct-new-declarator is zero,
the allocation function is called to allocate an array with no ele-
ments. The pointer returned by the new-expression is non-null.
[Note: If the library allocation function is called, the pointer
returned is distinct from the pointer to any other object. ]
8 A new-expression obtains storage for the object by calling an alloca-
tion function (_basic.stc.dynamic.allocation_). If the new-expression
terminates by throwing an exception, it may release storage by calling
a deallocation function (_basic.stc.dynamic.deallocation_). If the
allocated type is a non-array type, the allocation function's name is
operator new and the deallocation function's name is operator delete.
If the allocated type is an array type, the allocation function's name
is operator new[] and the deallocation function's name is
operator delete[]. [Note: an implementation shall provide default
definitions for the global allocation functions (_basic.stc.dynamic_,
_lib.new.delete.single_, _lib.new.delete.array_). A C++ program can
provide alternative definitions of these functions (_lib.replace-
ment.functions_) and/or class-specific versions (_class.free_). ]
9 If the new-expression begins with a unary :: operator, the allocation
function's name is looked up in the global scope. Otherwise, if the
allocated type is a class type T or array thereof, the allocation
function's name is looked up in the scope of T. If this lookup fails
to find the name, or if the allocated type is not a class type, the
allocation function's name is looked up in the global scope.
10A new-expression passes the amount of space requested to the alloca-
tion function as the first argument of type std::size_t. That argu-
ment shall be no less than the size of the object being created; it
may be greater than the size of the object being created only if the
object is an array. For arrays of char and unsigned char, the differ-
ence between the result of the new-expression and the address returned
by the allocation function shall be an integral multiple of the most
stringent alignment requirement (_basic.types_) of any object type
whose size is no greater than the size of the array being created.
[Note: Because allocation functions are assumed to return pointers to
storage that is appropriately aligned for objects of any type, this
constraint on array allocation overhead permits the common idiom of
allocating character arrays into which objects of other types will
later be placed. ]
11The new-placement syntax is used to supply additional arguments to an
allocation function. If used, overload resolution is performed on a
function call created by assembling an argument list consisting of the
amount of space requested (the first argument) and the expressions in
the new-placement part of the new-expression (the second and succeed-
ing arguments). The first of these arguments has type size_t and the
remaining arguments have the corresponding types of the expressions in
the new-placement.
12[Example:
--new T results in a call of operator new(sizeof(T)),
--new(2,f) T results in a call of operator new(sizeof(T),2,f),
--new T[5] results in a call of operator new[](sizeof(T)*5+x), and
--new(2,f) T[5] results in a call of
operator new[](sizeof(T)*5+y,2,f).
Here, x and y are non-negative unspecified values representing array
allocation overhead; the result of the new-expression will be offset
by this amount from the value returned by operator new[]. This over-
head may be applied in all array new-expressions, including those ref-
erencing the library function operator new[](std::size_t, void*) and
other placement allocation functions. The amount of overhead may vary
from one invocation of new to another. ]
13[Note: unless an allocation function is declared with an empty excep-
tion-specification (_except.spec_), throw(), it indicates failure to
allocate storage by throwing a bad_alloc exception (clause _except_,
_lib.bad.alloc_); it returns a non-null pointer otherwise. If the
allocation function is declared with an empty exception-specification,
throw(), it returns null to indicate failure to allocate storage and a
non-null pointer otherwise. ] If the allocation function returns
null, initialization shall not be done, the deallocation function
shall not be called, and the value of the new-expression shall be
null.
14[Note: when the allocation function returns a value other than null,
it must be a pointer to a block of storage in which space for the
object has been reserved. The block of storage is assumed to be
appropriately aligned and of the requested size. The address of the
created object will not necessarily be the same as that of the block
if the object is an array. ]
15A new-expression that creates an object of type T initializes that
object as follows:
--If the new-initializer is omitted:
--If T is a (possibly cv-qualified) non-POD class type (or array
thereof), the object is default-initialized (_dcl.init_) If T is a
const-qualified type, the underlying class type shall have a user-
declared default constructor.
--Otherwise, the object created has indeterminate value. If T is a
const-qualified type, or a (possibly cv-qualified) POD class type
(or array thereof) containing (directly or indirectly) a member of
const-qualified type, the program is ill-formed;
--If the new-initializer is of the form (), default-initialization
shall be performed (_dcl.init_);
--If the new-initializer is of the form expression-list) and T is a
class type, the appropriate constructor is called, using expression-
list as the arguments (_dcl.init_);
--If the new-initializer is of the form expression-list) and T is an
arithmetic, enumeration, pointer, or pointer-to-member type and
expression-list comprises exactly one expression, then the object is
initialized to the (possibly converted) value of the expression
(_dcl.init_);
--Otherwise the new-expression is ill-formed.
16If the new-expression creates an object or an array of objects of
class type, access and ambiguity control are done for the allocation
function, the deallocation function (_class.free_), and the construc-
tor (_class.ctor_). If the new expression creates an array of objects
of class type, access and ambiguity control are done for the destruc-
tor (_class.dtor_).
17If any part of the object initialization described above19) terminates
by throwing an exception and a suitable deallocation function can be
found, the deallocation function is called to free the memory in which
the object was being constructed, after which the exception continues
to propagate in the context of the new-expression. If no unambiguous
matching deallocation function can be found, propagating the exception
does not cause the object's memory to be freed. [Note: This is appro-
priate when the called allocation function does not allocate memory;
otherwise, it is likely to result in a memory leak. ]
18If the new-expression begins with a unary :: operator, the dealloca-
tion function's name is looked up in the global scope. Otherwise, if
the allocated type is a class type T or an array thereof, the deallo-
cation function's name is looked up in the scope of T. If this lookup
fails to find the name, or if the allocated type is not a class type
or array thereof, the deallocation function's name is looked up in the
global scope.
19A declaration of a placement deallocation function matches the decla-
ration of a placement allocation function if it has the same number of
parameters and, after parameter transformations (_dcl.fct_), all
parameter types except the first are identical. Any non-placement
deallocation function matches a non-placement allocation function. If
the lookup finds a single matching deallocation function, that func-
tion will be called; otherwise, no deallocation function will be
called.
20If a new-expression calls a deallocation function, it passes the value
returned from the allocation function call as the first argument of
_________________________
19) This may include evaluating a new-initializer and/or calling a
constructor.
type void*. If a placement deallocation function is called, it is
passed the same additional arguments as were passed to the placement
allocation function, that is, the same arguments as those specified
with the new-placement syntax. If the implementation is allowed to
make a copy of any argument as part of the call to the allocation
function, it is allowed to make a copy (of the same original value) as
part of the call to the deallocation function or to reuse the copy
made as part of the call to the allocation function. If the copy is
elided in one place, it need not be elided in the other.
21Whether the allocation function is called before evaluating the con-
structor arguments or after evaluating the constructor arguments but
before entering the constructor is unspecified. It is also unspeci-
fied whether the arguments to a constructor are evaluated if the allo-
cation function returns the null pointer or exits using an exception.
5.3.5 Delete [expr.delete]
1 The delete-expression operator destroys a most derived object
(_intro.object_) or array created by a new-expression.
delete-expression:
::opt delete cast-expression
::opt delete [ ] cast-expression
The first alternative is for non-array objects, and the second is for
arrays. The operand shall have a pointer type, or a class type having
a single conversion function (_class.conv.fct_) to a pointer type.
The result has type void.
2 If the operand has a class type, the operand is converted to a pointer
type by calling the above-mentioned conversion function, and the con-
verted operand is used in place of the original operand for the
remainder of this section. In either alternative, if the value of the
operand of delete is the null pointer the operation has no effect. In
the first alternative (delete object), the value of the operand of
delete shall be a pointer to a non-array object or a pointer to a sub-
object (_intro.object_) representing a base class of such an object
(clause _class.derived_). If not, the behavior is undefined. In the
second alternative (delete array), the value of the operand of delete
shall be the pointer value which resulted from a previous array
new-expression.20) If not, the behavior is undefined. [Note: this
means that the syntax of the delete-expression must match the type of
the object allocated by new, not the syntax of the new-expression. ]
[Note: a pointer to a const type can be the operand of a delete-
expression; it is not necessary to cast away the constness
(_expr.const.cast_) of the pointer expression before it is used as the
operand of the delete-expression. ]
3 In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
_________________________
20) For non-zero-length arrays, this is the same as a pointer to the
first element of the array created by that new-expression. Zero-
length arrays do not have a first element.
base class of the operand's dynamic type and the static type shall
have a virtual destructor or the behavior is undefined. In the second
alternative (delete array) if the dynamic type of the object to be
deleted differs from its static type, the behavior is undefined.21)
4 The cast-expression in a delete-expression shall be evaluated exactly
once. If the delete-expression calls the implementation deallocation
function (_basic.stc.dynamic.deallocation_), and if the operand of the
delete expression is not the null pointer constant, the deallocation
function will deallocate the storage referenced by the pointer thus
rendering the pointer invalid. [Note: the value of a pointer that
refers to deallocated storage is indeterminate. ]
5 If the object being deleted has incomplete class type at the point of
deletion and the complete class has a non-trivial destructor or a
deallocation function, the behavior is undefined.
6 The delete-expression will invoke the destructor (if any) for the
object or the elements of the array being deleted. In the case of an
array, the elements will be destroyed in order of decreasing address
(that is, in reverse order of the completion of their constructor; see
_class.base.init_).
7 The delete-expression will call a deallocation function
(_basic.stc.dynamic.deallocation_).
8 [Note: An implementation provides default definitions of the global
deallocation functions operator delete() for non-arrays
(_lib.new.delete.single_) and operator delete[]() for arrays
(_lib.new.delete.array_). A C++ program can provide alternative defi-
nitions of these functions (_lib.replacement.functions_), and/or
class-specific versions (_class.free_). ] When the keyword delete in
a delete-expression is preceded by the unary :: operator, the global
deallocation function is used to deallocate the storage.
9 Access and ambiguity control are done for both the deallocation func-
tion and the destructor (_class.dtor_, _class.free_).
5.4 Explicit type conversion (cast notation) [expr.cast]
1 The result of the expression (T) cast-expression is of type T. The
result is an lvalue if T is a reference type, otherwise the result is
an rvalue. [Note: if T is a non-class type that is cv-qualified, the
cv-qualifiers are ignored when determining the type of the resulting
rvalue; see _basic.lval_. ]
2 An explicit type conversion can be expressed using functional notation
(_expr.type.conv_), a type conversion operator (dynamic_cast,
static_cast, reinterpret_cast, const_cast), or the cast notation.
_________________________
21) This implies that an object cannot be deleted using a pointer of
type void* because there are no objects of type void.
cast-expression:
unary-expression
( type-id ) cast-expression
3 Types shall not be defined in casts.
4 Any type conversion not mentioned below and not explicitly defined by
the user (_class.conv_) is ill-formed.
5 The conversions performed by
--a const_cast (_expr.const.cast_),
--a static_cast (_expr.static.cast_),
--a static_cast followed by a const_cast,
--a reinterpret_cast (_expr.reinterpret.cast_), or
--a reinterpret_cast followed by a const_cast,
can be performed using the cast notation of explicit type conversion.
The same semantic restrictions and behaviors apply. If a conversion
can be interpreted in more than one of the ways listed above, the
interpretation that appears first in the list is used, even if a cast
resulting from that interpretation is ill-formed. If a conversion can
be interpreted in more than one way as a static_cast followed by a
const_cast, the conversion is ill-formed. [Example:
struct A {};
struct I1 : A {};
struct I2 : A {};
struct D : I1, I2 {};
A *foo( D *p ) {
return (A*)( p ); // ill-formed static_cast interpretation
}
--end example]
6 The operand of a cast using the cast notation can be an rvalue of type
"pointer to incomplete class type". The destination type of a cast
using the cast notation can be "pointer to incomplete class type". In
such cases, even if there is a inheritance relationship between the
source and destination classes, whether the static_cast or reinter-
pret_cast interpretation is used is unspecified.
7 In addition to those conversions, the following static_cast and rein-
terpret_cast operations (optionally followed by a const_cast opera-
tion) may be performed using the cast notation of explicit type con-
version, even if the base class type is not accessible:
--a pointer to an object of derived class type or an lvalue of derived
class type may be explicitly converted to a pointer or reference to
an unambiguous base class type, respectively;
--a pointer to member of derived class type may be explicitly
converted to a pointer to member of an unambiguous non-virtual base
class type;
--a pointer to an object of non-virtual base class type, an lvalue of
non-virtual base class type, or a pointer to member of non-virtual
base class type may be explicitly converted to a pointer, a refer-
ence, or a pointer to member of a derived class type, respectively.
5.5 Pointer-to-member operators [expr.mptr.oper]
1 The pointer-to-member operators ->* and .* group left-to-right.
pm-expression:
cast-expression
pm-expression .* cast-expression
pm-expression ->* cast-expression
2 The binary operator .* binds its second operand, which shall be of
type "pointer to member of T" (where T is a completely-defined class
type) to its first operand, which shall be of class T or of a class of
which T is an unambiguous and accessible base class. The result is an
object or a function of the type specified by the second operand.
3 The binary operator ->* binds its second operand, which shall be of
type "pointer to member of T" (where T is a completely-defined class
type) to its first operand, which shall be of type "pointer to T" or
"pointer to a class of which T is an unambiguous and accessible base
class." The result is an object or a function of the type specified
by the second operand.
4 If the dynamic type of the object does not contain the member to which
the pointer refers, the behavior is undefined.
5 The restrictions on cv-qualification, and the manner in which the cv-
qualifiers of the operands are combined to produce the cv-qualifiers
of the result, are the same as the rules for E1.E2 given in
_expr.ref_. [Note: it is not possible to use a pointer to member that
refers to a mutable member to modify a const class object. For exam-
ple,
struct S {
mutable int i;
};
const S cs;
int S::* pm = &S::i; // pm refers to mutable member S::i
cs.*pm = 88; // ill-formed: cs is a const object
]
6 If the result of .* or ->* is a function, then that result can be
used only as the operand for the function call operator (). [Example:
(ptr_to_obj->*ptr_to_mfct)(10);
calls the member function denoted by ptr_to_mfct for the object
pointed to by ptr_to_obj. ] The result of a .* expression is an
lvalue only if its first operand is an lvalue and its second operand
is a pointer to data member. The result of an ->* expression is an
lvalue only if its second operand is a pointer to data member. If the
second operand is the null pointer to member value (_conv.mem_), the
behavior is undefined.
5.6 Multiplicative operators [expr.mul]
1 The multiplicative operators *, /, and % group left-to-right.
multiplicative-expression:
pm-expression
multiplicative-expression * pm-expression
multiplicative-expression / pm-expression
multiplicative-expression % pm-expression
2 The operands of * and / shall have arithmetic or enumeration type; the
operands of % shall have integral or enumeration type. The usual
arithmetic conversions are performed on the operands and determine the
type of the result.
3 The binary * operator indicates multiplication.
4 The binary / operator yields the quotient, and the binary % operator
yields the remainder from the division of the first expression by the
second. If the second operand of / or % is zero the behavior is unde-
fined; otherwise (a/b)*b + a%b is equal to a. If both operands are
nonnegative then the remainder is nonnegative; if not, the sign of the
remainder is implementation-defined22).
5.7 Additive operators [expr.add]
1 The additive operators + and - group left-to-right. The usual arith-
metic conversions are performed for operands of arithmetic or enumera-
tion type.
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
For addition, either both operands shall have arithmetic or enumera-
tion type, or one operand shall be a pointer to a completely defined
object type and the other shall have integral or enumeration type.
2 For subtraction, one of the following shall hold:
--both operands have arithmetic or enumeration type; or
--both operands are pointers to cv-qualified or cv-unqualified ver-
sions of the same completely defined object type; or
--the left operand is a pointer to a completely defined object type
and the right operand has integral or enumeration type.
_________________________
22) According to work underway toward the revision of ISO C, the pre-
ferred algorithm for integer division follows the rules defined in the
ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is al-
ways rounded toward zero.
3 The result of the binary + operator is the sum of the operands. The
result of the binary - operator is the difference resulting from the
subtraction of the second operand from the first.
4 For the purposes of these operators, a pointer to a nonarray object
behaves the same as a pointer to the first element of an array of
length one with the type of the object as its element type.
5 When an expression that has integral type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If
the pointer operand points to an element of an array object, and the
array is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integral expression.
In other words, if the expression P points to the i-th element of an
array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
(where N has the value n) point to, respectively, the i+n-th and i-n-
th elements of the array object, provided they exist. Moreover, if
the expression P points to the last element of an array object, the
expression (P)+1 points one past the last element of the array object,
and if the expression Q points one past the last element of an array
object, the expression (Q)-1 points to the last element of the array
object. If both the pointer operand and the result point to elements
of the same array object, or one past the last element of the array
object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined.
6 When two pointers to elements of the same array object are subtracted,
the result is the difference of the subscripts of the two array ele-
ments. The type of the result is an implementation-defined signed
integral type; this type shall be the same type that is defined as
ptrdiff_t in the <cstddef> header (_lib.support.types_). As with any
other arithmetic overflow, if the result does not fit in the space
provided, the behavior is undefined. In other words, if the expres-
sions P and Q point to, respectively, the i-th and j-th elements of an
array object, the expression (P)-(Q) has the value i-j provided the
value fits in an object of type ptrdiff_t. Moreover, if the expres-
sion P points either to an element of an array object or one past the
last element of an array object, and the expression Q points to the
last element of the same array object, the expression ((Q)+1)-(P) has
the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value
zero if the expression P points one past the last element of the array
object, even though the expression (Q)+1 does not point to an element
of the array object. Unless both pointers point to elements of the
same array object, or one past the last element of the array object,
the behavior is undefined.23)
_________________________
23) Another way to approach pointer arithmetic is first to convert the
pointer(s) to character pointer(s): In this scheme the integral value
of the expression added to or subtracted from the converted pointer is
first multiplied by the size of the object originally pointed to, and
the resulting pointer is converted back to the original type. For
pointer subtraction, the result of the difference between the charac-
ter pointers is similarly divided by the size of the object originally
8 If the value 0 is added to or subtracted from a pointer value, the
result compares equal to the original pointer value. If two pointers
point to the same object or function or both point one past the end of
the same array or both are null, and the two pointers are subtracted,
the result compares equal to the value 0 converted to the type
ptrdiff_t.
5.8 Shift operators [expr.shift]
1 The shift operators << and >> group left-to-right.
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
The operands shall be of integral or enumeration type and integral
promotions are performed. The type of the result is that of the pro-
moted left operand. The behavior is undefined if the right operand is
negative, or greater than or equal to the length in bits of the pro-
moted left operand.
2 The value of E1 << E2 is E1 (interpreted as a bit pattern) left-
shifted E2 bit positions; vacated bits are zero-filled. If E1 has an
unsigned type, the value of the result is E1 multiplied by the quan-
tity 2 raised to the power E2, reduced modulo ULONG_MAX+1 if E1 has
type unsigned long, UINT_MAX+1 otherwise. [Note: the constants
ULONG_MAX and UINT_MAX are defined in the header <climits>). ]
3 The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has
an unsigned type or if E1 has a signed type and a nonnegative value,
the value of the result is the integral part of the quotient of E1
divided by the quantity 2 raised to the power E2. If E1 has a signed
type and a negative value, the resulting value is implementation-
defined.
5.9 Relational operators [expr.rel]
1 The relational operators group left-to-right. [Example: a<b<c means
(a<b)<c and not (a<b)&&(b<c). ]
relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
The operands shall have arithmetic, enumeration or pointer type. The
operators < (less than), > (greater than), <= (less than or equal to),
_________________________
pointed to.
7 When viewed in this way, an implementation need only provide one extra
byte (which might overlap another object in the program) just after
the end of the object in order to satisfy the "one past the last ele-
ment" requirements.
and >= (greater than or equal to) all yield false or true. The type
of the result is bool.
2 The usual arithmetic conversions are performed on operands of arith-
metic or enumeration type. Pointer conversions (_conv.ptr_) and qual-
ification conversions (_conv.qual_) are performed on pointer operands
(or on a pointer operand and a null pointer constant) to bring them to
their composite pointer type. If one operand is a null pointer con-
stant, the composite pointer type is the type of the other operand.
Otherwise, if one of the operands has type "pointer to cv1 void", then
the other has type "pointer to cv2 T" and the composite pointer type
is "pointer to cv12 void", where cv12 is the union of cv1 and cv2.
Otherwise, the composite pointer type is a pointer type similar
(_conv.qual_) to the type of one of the operands, with a cv-qualifica-
tion signature (_conv.qual_) that is the union of the cv-qualification
signatures of the operand types. [Note: this implies that any pointer
can be compared to a null pointer constant and that any object pointer
can be compared to a pointer to (possibly cv-qualified) void. ]
[Example:
void *p;
const int *q;
int **pi;
const int *const *pci;
void ct()
{
p <= q; // Both converted to const void * before comparison
pi <= pci; // Both converted to const int *const * before comparison
}
--end example] Pointers to objects or functions of the same type
(after pointer conversions) can be compared, with a result defined as
follows:
--If two pointers p and q of the same type point to the same object or
function, or both point one past the end of the same array, or are
both null, then p<=q and p>=q both yield true and p<q and p>q both
yield false.
--If two pointers p and q of the same type point to different objects
that are not members of the same object or elements of the same
array or to different functions, or if only one of them is null, the
results of p<q, p>q, p<=q, and p>=q are unspecified.
--If two pointers point to nonstatic data members of the same object,
or to subobjects or array elements of such members, recursively, the
pointer to the later declared member compares greater provided the
two members are not separated by an access-specifier label
(_class.access.spec_) and provided their class is not a union.
--If two pointers point to nonstatic data members of the same object
separated by an access-specifier label (_class.access.spec_) the
result is unspecified.
--If two pointers point to data members of the same union object, they
compare equal (after conversion to void*, if necessary). If two
pointers point to elements of the same array or one beyond the end
of the array, the pointer to the object with the higher subscript
compares higher.
--Other pointer comparisons are unspecified.
5.10 Equality operators [expr.eq]
1 equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
The == (equal to) and the != (not equal to) operators have the same
semantic restrictions, conversions, and result type as the relational
operators except for their lower precedence and truth-value result.
[Note: a<b == c<d is true whenever a<b and c<d have the same truth-
value. ] Pointers to objects or functions of the same type (after
pointer conversions) can be compared for equality. Two pointers of
the same type compare equal if and only if they are both null, both
point to the same object or function, or both point one past the end
of the same array.
2 In addition, pointers to members can be compared, or a pointer to mem-
ber and a null pointer constant. Pointer to member conversions
(_conv.mem_) and qualification conversions (_conv.qual_) are performed
to bring them to a common type. If one operand is a null pointer con-
stant, the common type is the type of the other operand. Otherwise,
the common type is a pointer to member type similar (_conv.qual_) to
the type of one of the operands, with a cv-qualification signature
(_conv.qual_) that is the union of the cv-qualification signatures of
the operand types. [Note: this implies that any pointer to member can
be compared to a null pointer constant. ] If both operands are null,
they compare equal. Otherwise if only one is null, they compare
unequal. Otherwise if either is a pointer to a virtual member func-
tion, the result is unspecified. Otherwise they compare equal if and
only if they would refer to the same member of the same most derived
object (_intro.object_) or the same subobject if they were derefer-
enced with a hypothetical object of the associated class type. [Exam-
ple:
struct B {
int f();
};
struct L : B { };
struct R : B { };
struct D : L, R { };
int (B::*pb)() = &B::f;
int (L::*pl)() = pb;
int (R::*pr)() = pb;
int (D::*pdl)() = pl;
int (D::*pdr)() = pr;
bool x = (pdl == pdr); // false
--end example]
5.11 Bitwise AND operator [expr.bit.and]
1 and-expression:
equality-expression
and-expression & equality-expression
The usual arithmetic conversions are performed; the result is the bit-
wise function of the operands. The operator applies only to integral
or enumeration operands.
5.12 Bitwise exclusive OR operator [expr.xor]
1 exclusive-or-expression:
and-expression
exclusive-or-expression ^ and-expression
The usual arithmetic conversions are performed; the result is the bit-
wise exclusive function of the operands. The operator applies only to
integral or enumeration operands.
5.13 Bitwise inclusive OR operator [expr.or]
1 inclusive-or-expression:
exclusive-or-expression
inclusive-or-expression | exclusive-or-expression
The usual arithmetic conversions are performed; the result is the bit-
wise inclusive function of its operands. The operator applies only to
integral or enumeration operands.
5.14 Logical AND operator [expr.log.and]
1 logical-and-expression:
inclusive-or-expression
logical-and-expression && inclusive-or-expression
The && operator groups left-to-right. The operands are both implic-
itly converted to type bool (clause _conv_). The result is true if
both operands are true and false otherwise. Unlike &, && guarantees
left-to-right evaluation: the second operand is not evaluated if the
first operand is false.
2 The result is a bool. All side effects of the first expression except
for destruction of temporaries (_class.temporary_) happen before the
second expression is evaluated.
5.15 Logical OR operator [expr.log.or]
1 logical-or-expression:
logical-and-expression
logical-or-expression || logical-and-expression
The || operator groups left-to-right. The operands are both implic-
itly converted to bool (clause _conv_). It returns true if either of
its operands is true, and false otherwise. Unlike |, || guarantees
left-to-right evaluation; moreover, the second operand is not evalu-
ated if the first operand evaluates to true.
2 The result is a bool. All side effects of the first expression except
for destruction of temporaries (_class.temporary_) happen before the
second expression is evaluated.
5.16 Conditional operator [expr.cond]
1 conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
Conditional expressions group right-to-left. The first expression is
implicitly converted to bool (clause _conv_). It is evaluated and if
it is true, the result of the conditional expression is the value of
the second expression, otherwise that of the third expression. All
side effects of the first expression except for destruction of tempo-
raries (_class.temporary_) happen before the second or third expres-
sion is evaluated. Only one of the second and third expressions is
evaluated.
2 If either the second or the third operand has type (possibly cv-quali-
fied) void, then the lvalue-to-rvalue (_conv.lval_), array-to-pointer
(_conv.array_), and function-to-pointer (_conv.func_) standard conver-
sions are performed on the second and third operands, and one of the
following shall hold:
--The second or the third operand (but not both) is a throw-expression
(_except.throw_); the result is of the type of the other and is an
rvalue.
--Both the second and the third operands have type void; the result is
of type void and is an rvalue. [Note: this includes the case where
both operands are throw-expressions. ]
3 Otherwise, if the second and third operand have different types, and
either has (possibly cv-qualified) class type, an attempt is made to
convert each of those operands to the type of the other. The process
for determining whether an operand expression E1 of type T1 can be
converted to match an operand expression E2 of type T2 is defined as
follows:
--If E2 is an lvalue: E1 can be converted to match E2 if E1 can be
implicitly converted (clause _conv_) to the type "reference to T2",
subject to the constraint that in the conversion the reference must
bind directly (_dcl.init.ref_) to E1.
--If E2 is an rvalue, or if the conversion above cannot be done:
--if E1 and E2 have class type, and the underlying class types are
the same or one is a base class of the other: E1 can be converted
to match E2 if the class of T2 is the same type as, or a base
class of, the class of T1, and the cv-qualification of T2 is the
same cv-qualification as, or a greater cv-qualification than, the
cv-qualification of T1. If the conversion is applied, E1 is
changed to an rvalue of type T2 that still refers to the original
source class object (or the appropriate subobject thereof).
[Note: that is, no copy is made. ]
--Otherwise (i.e., if E1 or E2 has a nonclass type, or if they both
have class types but the underlying classes are not either the
same or one a base class of the other): E1 can be converted to
match E2 if E1 can be implicitly converted to the type that
expression E2 would have if E2 were converted to an rvalue (or the
type it has, if E2 is an rvalue).
Using this process, it is determined whether the second operand can
be converted to match the third operand, and whether the third
operand can be converted to match the second operand. If both can
be converted, or one can be converted but the conversion is ambigu-
ous, the program is ill-formed. If neither can be converted, the
operands are left unchanged and further checking is performed as
described below. If exactly one conversion is possible, that con-
version is applied to the chosen operand and the converted operand
is used in place of the original operand for the remainder of this
section.
4 If the second and third operands are lvalues and have the same type,
the result is of that type and is an lvalue.
5 Otherwise, the result is an rvalue. If the second and third operand
do not have the same type, and either has (possibly cv-qualified)
class type, overload resolution is used to determine the conversions
(if any) to be applied to the operands (_over.match.oper_,
_over.built_). If the overload resolution fails, the program is ill-
formed. Otherwise, the conversions thus determined are applied, and
the converted operands are used in place of the original operands for
the remainder of this section.
6 Lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_), and
function-to-pointer (_conv.func_) standard conversions are performed
on the second and third operands. After those conversions, one of the
following shall hold:
--The second and third operands have the same type; the result is of
that type.
--The second and third operands have arithmetic or enumeration type;
the usual arithmetic conversions are performed to bring them to a
common type, and the result is of that type.
--The second and third operands have pointer type, or one has pointer
type and the other is a null pointer constant; pointer conversions
(_conv.ptr_) and qualification conversions (_conv.qual_) are per-
formed to bring them to their composite pointer type (_expr.rel_).
The result is of the composite pointer type.
--The second and third operands have pointer to member type, or one
has pointer to member type and the other is a null pointer constant;
pointer to member conversions (_conv.mem_) and qualification conver-
sions (_conv.qual_) are performed to bring them to a common type,
whose cv-qualification shall match the cv-qualification of either
the second or the third operand. The result is of the common type.
5.17 Assignment operators [expr.ass]
1 There are several assignment operators, all of which group right-to-
left. All require a modifiable lvalue as their left operand, and the
type of an assignment expression is that of its left operand. The
result of the assignment operation is the value stored in the left
operand after the assignment has taken place; the result is an lvalue.
assignment-expression:
conditional-expression
logical-or-expression assignment-operator assignment-expression
throw-expression
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=
2 In simple assignment =), the value of the expression replaces that of
the object referred to by the left operand.
3 If the left operand is not of class type, the expression is implicitly
converted (clause _conv_) to the cv-unqualified type of the left
operand.
4 If the left operand is of class type, the class shall be complete.
Assignment to objects of a class is defined by the copy assignment
operator (_class.copy_, _over.ass_).
5 [Note: For class objects, assignment is not in general the same as
initialization (_dcl.init_, _class.ctor_, _class.init_, _class.copy_).
]
6 When the left operand of an assignment operator denotes a reference to
T, the operation assigns to the object of type T denoted by the refer-
ence.
7 The behavior of an expression of the form E1 op= E2 is equivalent to
E1=E1 op E2 except that E1 is evaluated only once. In += and -=, E1
shall either have arithmetic type or be a pointer to a possibly cv-
qualified completely defined object type. In all other cases, E1
shall have arithmetic type.
8 If the value being stored in an object is accessed from another object
that overlaps in any way the storage of the first object, then the
overlap shall be exact and the two objects shall have the same type,
otherwise the behavior is undefined.
5.18 Comma operator [expr.comma]
1 The comma operator groups left-to-right.
expression:
assignment-expression
expression , assignment-expression
A pair of expressions separated by a comma is evaluated left-to-right
and the value of the left expression is discarded. The lvalue-to-
rvalue (_conv.lval_), array-to-pointer (_conv.array_), and function-
to-pointer (_conv.func_) standard conversions are not applied to the
left expression. All side effects (_intro.execution_) of the left
expression, except for the destruction of temporaries (_class.tempo-
rary_), are performed before the evaluation of the right expression.
The type and value of the result are the type and value of the right
operand; the result is an lvalue if its right operand is.
2 In contexts where comma is given a special meaning, [Example: in lists
of arguments to functions (_expr.call_) and lists of initializers
(_dcl.init_) ] the comma operator as described in clause _expr_ can
appear only in parentheses. [Example:
f(a, (t=3, t+2), c);
has three arguments, the second of which has the value 5. ]
5.19 Constant expressions [expr.const]
1 In several places, C++ requires expressions that evaluate to an inte-
gral or enumeration constant: as array bounds (_dcl.array_,
_expr.new_), as case expressions (_stmt.switch_), as bit-field lengths
(_class.bit_), as enumerator initializers (_dcl.enum_), as static mem-
ber initializers (_class.static.data_), and as integral or enumeration
non-type template arguments (_temp.arg_).
constant-expression:
conditional-expression
An integral constant-expression can involve only literals (_lex.lit-
eral_), enumerators, const variables or static data members of inte-
gral or enumeration types initialized with constant expressions
(_dcl.init_), non-type template parameters of integral or enumeration
types, and sizeof expressions. Floating literals (_lex.fcon_) can
appear only if they are cast to integral or enumeration types. Only
type conversions to integral or enumeration types can be used. In
particular, except in sizeof expressions, functions, class objects,
pointers, or references shall not be used, and assignment, increment,
decrement, function-call, or comma operators shall not be used.
2 Other expressions are considered constant-expressions only for the
purpose of non-local static object initialization
(_basic.start.init_). Such constant expressions shall evaluate to one
of the following:
--a null pointer value (_conv.ptr_),
--a null member pointer value (_conv.mem_),
--an arithmetic constant expression,
--an address constant expression,
--a reference constant expression,
--an address constant expression for a complete object type, plus or
minus an integral constant expression, or
--a pointer to member constant expression.
3 An arithmetic constant expression shall have arithmetic or enumeration
type and shall only have operands that are integer literals
(_lex.icon_), floating literals (_lex.fcon_), enumerators, character
literals (_lex.ccon_) and sizeof expressions (_expr.sizeof_). Cast
operators in an arithmetic constant expression shall only convert
arithmetic or enumeration types to arithmetic or enumeration types,
except as part of an operand to the sizeof operator.
4 An address constant expression is a pointer to an lvalue designating
an object of static storage duration, a string literal (_lex.string_),
or a function. The pointer shall be created explicitly, using the
unary & operator, or implicitly using a non-type template parameter of
pointer type, or using an expression of array (_conv.array_) or func-
tion (_conv.func_) type. The subscripting operator [] and the class
member access . and -> operators, the & and * unary operators, and
pointer casts (except dynamic_casts, _expr.dynamic.cast_) can be used
in the creation of an address constant expression, but the value of an
object shall not be accessed by the use of these operators. If the
subscripting operator is used, one of its operands shall be an inte-
gral constant expression. An expression that designates the address
of a member or base class of a non-POD class object (clause _class_)
is not an address constant expression (_class.cdtor_). Function calls
shall not be used in an address constant expression, even if the func-
tion is inline and has a reference return type.
5 A reference constant expression is an lvalue designating an object of
static storage duration, a non-type template parameter of reference
type, or a function. The subscripting operator [], the class member
access . and -> operators, the & and * unary operators, and reference
casts (except those invoking user-defined conversion functions
(_class.conv.fct_) and except dynamic_casts (_expr.dynamic.cast_)) can
be used in the creation of a reference constant expression, but the
value of an object shall not be accessed by the use of these opera-
tors. If the subscripting operator is used, one of its operands shall
be an integral constant expression. An lvalue expression that desig-
nates a member or base class of a non-POD class object (clause
_class_) is not a reference constant expression (_class.cdtor_).
Function calls shall not be used in a reference constant expression,
even if the function is inline and has a reference return type.
6 A pointer to member constant expression shall be created using the
unary & operator applied to a qualified-id operand (_expr.unary.op_),
optionally preceded by a pointer to member cast (_expr.static.cast_).