______________________________________________________________________
5 Expressions [expr]______________________________________________________________________
1 [Note: this clause defines the syntax, order of evaluation, and mean­
ing 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 (_class_). Uses of overloaded operators are
transformed into function calls as described in _over.oper_. Over­
loaded operators obey the rules for syntax specified in this clause,
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_).1) ]
3 This clause defines the 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 operators applied to
types for which they are defined by the language itself. However,
these built-in operators participate in overload resolution; see
_over.match.oper_.
4 Operators can be regrouped according to the usual mathematical rules
only where the operators really are associative or commutative. Over­
loaded operators are never assumed to be associative or commutative.
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. 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:i = v[i++]; // the behavior is undefinedi = 7,i++,i++; // `i' becomes 9i = ++i + 1; // the behavior is undefinedi = i + 1; // the value of 'i' is incremented
--end example]
_________________________
1) Nor is it guaranteed for type bool; the left operand of += shall
not have type bool.
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. [Note: most existing implementations
of C++ ignore integer overflows. Treatment of division by zero and
all floating point exceptions vary among machines, and is usually
adjustable by a library function. ]
+------- BEGIN BOX 1 -------+
ISO C recently dealt with a Defect Report which asked whether a com­
pile-time diagnostic was permissible in cases where the undefined
behavior would occur in evaluating a compile-time constant expression.
WG14 decided that it was permissible - we probably need equivalent
wording here.
+------- END BOX 1 -------+
6 Except where noted, operands of types const T, volatile T, T&,
const T&, and volatile T& can be used as if they were of the plain
type T. Similarly, except where noted, operands of type T* const and
T* volatile can be used as if they were of the plain type T*. Simi­
larly, a plain T can be used where a volatile T or a const T is
required. These rules apply in combination so that, except where
noted, a T* const volatile can be used where a T* is required. Such
uses do not count as standard conversions when considering overloading
resolution (_over.match_).
7 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. A reference can be
thought of as a name of an object.
8 An expression designating an object is called an object-expression.
9 User-defined conversions of class types to and from fundamental types,
pointers, and so on, can be defined (_class.conv_). If unambiguous
(_over.match_), such conversions are applied wherever a class object
appears as an operand of an operator or as a function argument
(_expr.call_).
10Whenever 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 conversion are applied to convert the expres­
sion to an rvalue.
11Many binary operators that expect operands of arithmetic 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."
+------- BEGIN BOX 2 -------+
Enumerations are handled correctly by the usual arithmetic conver­
sions, and for any operator that invokes the integral promotions.
However, there may be other places in this Clause that fail to treat
enumerations appropriately.
+------- END BOX 2 -------+
12The processor shall perform the following conversions on operands of
arithmetic type:
--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)
--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 ]
13If the program attempts to access the stored value of an object
through an lvalue of other than one of the following types the behav­
ior is undefined:
--the dynamic type of the object,
--a cv-qualified version of the declared type of the object,
--a type that is the signed or unsigned type corresponding to the
declared type of the object,
--a type that is the signed or unsigned type corresponding to a cv-
qualified version of the declared type of the object,
_________________________
2) As a consequence, operands of type bool, wchar_t, or an enumerated
type are converted to some integral type.
--an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a sub­
aggregate or contained union),
--a type that is a (possibly cv-qualified) base class type of the
declared type of the object,
--a char or unsigned char type.3)
5.1 Primary expressions[expr.prim]
1 Primary expressions are literals, names, and names qualified by the
scope resolution operator ::.
primary-expression:literalthis::identifier::operator-function-id::qualified-id(expression)id-expression
2 A literal is a primary expression. Its type depends on its form
(_lex.literal_).
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_)
or in a constructor mem-initializer (_class.base.init_).
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, name, or operator-function-id. The
result is the identifier, name, or operator-function-id. The result
is an lvalue if the identifier, name, or operator-function-id is. The
identifier, name, or operator-function-id shall be of global namespace
scope. [Note: the use of :: allows a type, an object, a function, or
an enumerator declared in the global namespace to be referred to even
if its identifier has been hidden (_basic.scope_). ]
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.
6 A id-expression is a restricted form of a primary-expression that can
appear after . and -> (_expr.ref_):
_________________________
3) The intent of this list is to specify those circumstances in which
an object may or may not be aliased.
id-expression:unqualified-idqualified-idunqualified-id:identifieroperator-function-idconversion-function-id~ class-nametemplate-id
+------- BEGIN BOX 3 -------+
Issue: now it's allowed to invoke ~int(), but ~class-name doesn't
allow for that.
+------- END BOX 3 -------+
7 An identifier is an id-expression provided it has been suitably
declared (_dcl.dcl_). [Note: for operator-function-ids, see
_over.oper_; for conversion-function-ids, see _class.conv.fct_. A
class-name prefixed by ~ denotes a destructor; see _class.dtor_. ]
8 qualified-id:nested-name-specifiertemplateopt unqualified-id
A nested-name-specifier that names a class (_dcl.type_) followed by
::, 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 (_class.derived_), is a qual­ified-id. If the qualified-id refers to a non-static member, its type
is the data member type or function member type (_class.mem_); if it
refers to a static member, its type is an object or function type
(_class.static_). The result is the member. The result is an lvalue
if the member is. If the class-name is hidden by a name that is not a
type name or namespace-name, the class-name is still found and used.
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_).
9 A nested-name-specifier that names a namespace (_basic.namespace_)
followed by ::, followed by the name of a member of that namespace is
a qualified-id; names introduced by using-directives (_names­
pace.udir_) in the namespace denoted by the nested-name-specifier are
ignored for the purpose of this member lookup. The type of the quali­fied-id is the type of the member. The result is the member. The
result is an lvalue if the member is. If the namespace-name is hidden
by a name that is not a type name, the namespace-name is still found
and used.
10Multiply qualified names, such as N1::N2::N3::n, can be used to refer
to nested types (_class.nest_).
11In 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.
12An id-expression that denotes a nonstatic member 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_).
13A template-id shall be used as an unqualified-id only as specified in
clauses _temp.explicit_, _temp.spec_, and _temp.class.spec_.
5.2 Postfix expressions[expr.post]
1 Postfix expressions group left-to-right.
postfix-expression:primary-expressionpostfix-expression[expression]postfix-expression(expression-listopt)simple-type-specifier(expression-listopt)postfix-expression. templateopt id-expressionpostfix-expression-> templateopt id-expressionpostfix-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-expressionexpression-list,assignment-expression5.2.1 Subscripting[expr.sub]
1 A postfix expression followed by an expression in square brackets is a
postfix expression. [Note: the intuitive meaning is that of a sub­
script. ] One of the expressions shall have the type "pointer to T"
and the other shall be of enumeration or integral type. The result is
an lvalue of type "T." The type "T" shall be complete. 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 function4) (_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 ordinary function call, the postfix expression shall be
a function name, or a pointer or reference to a function. For 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 (_over_), in which case the appro­
priate function shall be selected according to the rules in
_over.match_. The function called in a member function call is nor­
mally selected according to the static type of the object expression
(see _class.derived_), but if that function is virtual 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 type of the object pointed or referred to by the current value of
the object expression. Clause _class.cdtor_ describes the behavior of
virtual function calls when the object-expression refers to an object
under construction or destruction. ]
2 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 complete or the type void.
3 When a function is called, each parameter (_dcl.fct_) shall be ini­
tialized (_dcl.init.ref_, _class.copy_, _class.ctor_) with its corre­
sponding argument. Standard (_conv_) and user-defined (_class.conv_)
conversions shall be performed. The value of a function call is the
value returned by the called function except in a virtual function
call if the return type of the final overrider is different from the
return type of the statically chosen function, the value returned from
the final overrider is converted to the return type of the statically
chosen function.
4 [Note: a function can change the values of its nonconstant parameters,
but these changes cannot affect the values of the arguments except
_________________________
4) A static member function (_class.static_) is an ordinary function.
where a parameter is of a non-const reference type (_dcl.ref_). Where
a parameter is of 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 modify the values
of nonconstant objects through pointer parameters.
5 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_). ]
6 If no declaration of the called function is accessible from the scope
of the call the program is ill-formed. [Note: this implies that,
except where the ellipsis (...) is used, a parameter is available for
each argument. ]
7 Any argument of type float for which there is no parameter is con­
verted to double before the call; any of char, short, or a bit-field
type for which there is no parameter are converted to int or unsigned
by integral promotion (_conv.prom_). Any argument of enumeration type
is converted to int, unsigned, long, or unsigned long by integral pro­
motion. An argument of a POD class type T, for which no corresponding
parameter is declared, is passed in a manner such that the receiving
function can obtain its value by an invocation of va_arg(T). If an
argument of a non-POD class type is passed, and there is no corre­
sponding parameter, the behavior is undefined.
8 [Note: an argument of class type for which a corresponding parameter
is declared is passed according to the rules above. ]
9 The order of evaluation of arguments is unspecified. All side effects
of argument expressions take effect before the function is entered.
The order of evaluation of the postfix expression and the argument
expression list is unspecified.
10The function-to-pointer standard conversion (_conv.func_) is sup­
pressed on the postfix expression of a function call.
11Recursive calls are permitted.
12A 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 specifies a single value, the
expression is equivalent (in definedness, and if defined in meaning)
to the corresponding cast expression (_expr.cast_). 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.simple_), creates an rvalue of the specified type, whose
value is determined by default-initialization (_dcl.init_).
5.2.4 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;5) 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
type). The id-expression shall name a member of that class, except
that an imputed destructor can be explicitly invoked for a scalar type
(_class.dtor_). 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 this subclause will address only the first option
(dot)6).
3 If the id-expression is a qualified-id, the nested-name-specifier of
the qualified-id can specify a namespace name or a class name. If the
nested-name-specifier of the qualified-id specifies a namespace name,
the name is looked up in the context in which the entire postfix-expression occurs. If the nested-name-specifier of the qualified-id
specifies a class name, the class name is looked up as a type both in
the class of the object expression (or the class pointed to by the
pointer expression) and the context in which the entire postfix-expression occurs. [Note: by the "injection" rules, the name, if any,
of each class is also considered a nested class member of that class.
] These searches shall yield a single type. [Note: the type might be
found in either or both contexts. ] If the nested-name-specifier con­
tains a class template-id (_temp.names_), its template-arguments are
evaluated in the context in which the entire postfix-expression
occurs.
4 Similarly, if the id-expression is a conversion-function-id, its con­version-type-id shall denote the same type in both the context in
which the entire postfix-expression occurs and in the context of the
_________________________
5) 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.
6) Note that if E1 has the type "pointer to class X", then (*(E1)) is
an lvalue.
class of the object expression (or the class pointed to by the pointer
expression).
5 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 this subclause, 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_.
6 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 (possibly overloaded) 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".
--If E2 is a non-static data member, and the type of E1 is "cq1 vq1X", and the type of E2 is "cq2 vq2T", 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 "vq12T". If E2 is not declared to
be a mutable member, then the type of E1.E2 is "cq12 vq12T".
--If E2 is a (possibly overloaded) non-static member function, and the
type of E2 is "cv function of (parameter type list) returning T",
then E1.E2 is not an lvalue. The expression designates a member
function (of some class X). The expression can be used only as the
left-hand operand of a member function call (_class.mfct_). The
member function shall be at least as cv-qualified as E1. The type
of E1.E2 is "class X's cv member function of (parameter type list)
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.
+------- BEGIN BOX 4 -------+
This does not cover the case where E2 is the overloaded name of a mem­
ber function that includes both static and non-static versions.
+------- END BOX 4 -------+
7 [Note: "class objects" can be structures (_class.mem_) and unions
(_class.union_). Classes are discussed in clause _class_. ]
5.2.5 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 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.
] The type of the result is the same as the type of the operand, but
it is not an lvalue. 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.
5.2.6 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 cvvoid". 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 can be con­
verted to R via a qualification conversion (_conv.qual_) in the
pointer case, 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 cv1B" and v has type "pointer to cv2D" 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 cv1B" and v has type cv2D" such that B is a base class of D, the
result is an lvalue for the unique7) 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,
_________________________
7) The complete object pointed or referred to by v can contain other B
objects as base classes, but these are ignored.
cv2, and B shall be an accessible nonambiguous base class of D.
[Example:struct B {};struct D : B {};void foo(D* dp){B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;}
--end example]
6 Otherwise, v shall be a pointer to or an lvalue of a polymorphic type
(_class.virtual_).
7 If T is "pointer to cvvoid," then the result is a pointer to the com­
plete object (_class.base.init_) pointed to by v. Otherwise, a run-
time check is applied to see if the object pointed or referred to by v
can be converted to the type pointed or referred to by T.
8 The run-time check logically executes like this: If, in the complete
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 referred to by v, the result is a pointer
(an lvalue referring) to that T object. Otherwise, if the type of the
complete object has an unambiguous public base class of type T, the
result is a pointer (reference) to the T sub-object of the complete
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: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 protectionA* ap = &d; // public derivation, no cast neededD& dr = dynamic_cast<D&>(*bp); // succeedsap = dynamic_cast<A*>(bp); // succeedsbp = dynamic_cast<B*>(ap); // failsap = dynamic_cast<A*>(&dr); // succeedsbp = dynamic_cast<B*>(&dr); // fails}class E : public D , public B {};class F : public E, public D {}void h(){F f;A* ap = &f; // okay: finds unique AD* dp = dynamic_cast<D*>(ap); // fails: ambiguousE* ep = (E*)ap; // error: cast from virtual baseE* ep = dynamic_cast<E*>(ap); // succeeds}
--end example] [Note: Clause _class.cdtor_ describes the behavior of
a dynamic_cast applied to an object under construction or destruction.
]
5.2.7 Type identification[expr.typeid]
1 The result of a typeid expression is of type const type_info&. The
value is a reference to a type_info object (_lib.type.info_) that rep­
resents the type-id or the type of the expression respectively.
2 If the expression is a reference to a polymorphic type
(_class.virtual_), the type_info for the complete object
(_class.base.init_) referred to is the result.
3 If the expression is the result of applying unary * to a pointer to a
polymorphic type,8) then the pointer shall either be zero or point to
a valid object. If the pointer is zero, the typeid expression throws
the bad_typeid exception (_lib.bad.typeid_). Otherwise, the result of
the typeid expression is the value that represents the type of the
complete object to which the pointer points.
4 If the expression is the result of subscripting (_expr.sub_) a
pointer, say p, that points to a polymorphic type,9) then the result
of the typeid expression is that of typeid(*p). The subscript is not
evaluated.
5 If the expression is neither a pointer nor a reference to a polymor­
phic type, the result is the type_info representing the (static) type
of the expression. The expression is not evaluated.
6 In all cases typeid ignores the top-level cv-qualifiers of its
operand's type. [Example:class D { ... };D d1;const D d2;typeid(d1) == typeid(d2); // yields truetypeid(D) == typeid(const D); // yields truetypeid(D) == typeid(d2); // yields true
--end example] [Note: Clause _class.cdtor_ describes the behavior of
typeid applied to an object under construction or destruction. ]
5.2.8 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
_________________________
8) If p is a pointer, then *p, (*p), ((*p)), and so on all meet this
requirement.
9) If p is a pointer to a polymorphic type and i has integral or enu­
merated type, then p[i], (p[i]), (p)[i], ((((p))[((i))])), i[p],
(i[p]), and so on all meet this requirement.
cast away constness. See _expr.const.cast_.
2 Any implicit conversion (including standard conversions and/or user-
defined conversions; see _conv_ and _over.best.ics_) can be performed
explicitly using static_cast. More precisely, if T t(v); is a well-
formed declaration, for some invented temporary variable t, then the
result of static_cast<T>(v) is defined to be the temporary t, and is
an lvalue if T is a reference type, and an rvalue otherwise. The
expression v shall be an lvalue if the equivalent declaration requires
an lvalue for v.
3 If the static_cast does not correspond to an implicit conversion by
the above definition, it shall perform one of the conversions listed
below. No other conversion can be performed explicitly using a
static_cast.
4 Any expression can be explicitly converted to type cvvoid." The
expression value is discarded.
5 An lvalue expression of type T1 can be cast to the type "reference to
T2" if an expression of type "pointer to T1" can be explicitly con­
verted to the type "pointer to T2" using a static_cast. That is, a
reference cast static_cast<T&>x has the same effect as the conversion
*static_cast<T*>&x with the built-in & and * operators. The result is
an lvalue. This interpretation is used only if the original
static_cast is not well-formed as an implicit conversion under the
rules given above. This form of reference cast creates an lvalue that
refers to the same object as the source lvalue, but with a different
type. [Note: it does not create a temporary or copy the object, and
constructors (_class.ctor_) or conversion functions (_class.conv_) are
not called. For example,
struct B {};struct D : public B {};D d;// creating a temporary for the B sub-object not allowed... (const B&) d ...
--end note]
6 The inverse of any standard conversion (_conv_), other than the
lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_), and
function-to-pointer (_conv.func_) 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 resulting
enumeration value is unspecified.
8 An rvalue of type "pointer to cv1B", where B is a class type, can be
converted to an rvalue of type "pointer to cv2D", where D is a class
derived (_class.derived_) from B, if a valid standard conversion from
"pointer to cv2D" to "pointer to cv2B" 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 cv1B" 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 cv1T" can be con­
verted to an rvalue of type "pointer to member of B of type cv2T",
where B is a base class (_class.derived_) of D, if a valid standard
conversion from "pointer to member of B of type cv2T" to "pointer to
member of D of type cv2T" exists (_conv.mem_), and cv2 is the same
cv-qualification as, or greater cv-qualification than, cv1. The null
member pointer value (_conv.mem_) is converted to the null member
pointer value of the destination type. If class B contains or inher­
its the original member, the resulting pointer to member points to the
member in class B. Otherwise, the result of the cast is undefined.
5.2.9 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. Types shall
not be defined in a reinterpret_cast. Conversions that can be per­
formed explicitly using reinterpret_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''. ]
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 can be explicitly converted to a pointer. A
pointer converted to an integer of sufficient size (if any such exists
on the implementation) and back to the same pointer type will have its
original value; mappings between pointers and integers are otherwise
implementation-defined.
6 The operand of a pointer cast can be an rvalue of type "pointer to
incomplete class type". The destination type of a pointer cast can be
"pointer to incomplete class type". In such cases, if there is any
inheritance relationship between the source and destination classes,
the behavior is undefined.
7 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 that differs from the type used
in the definition of the function is undefined. Except that convert­
ing 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 con­
version is unspecified; [Note: see also _conv.ptr_ for more details of
pointer conversions. ]
8 A pointer to an object can be explicitly converted to a pointer to an
object of different type. 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;
9 The null pointer value (_conv.ptr_) is converted to the null pointer
value of the destination type.
10An 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 data member types.
The null member pointer value (_conv.mem_) is converted to the null
member pointer value of the destination type. The result of this con­
version 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.
11Calling a member function through a pointer to member that represents
a function type that differs from the function type specified on the
member function declaration results in undefined behavior.
12An 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 con­
version *reinterpret_cast<T*>&x with the built-in & and * operators.
The result is an lvalue that refers to the same object as the source
lvalue, but with a different type. No temporary is created, no copy
is made, and constructors (_class.ctor_) or conversion functions
(_class.conv_) are not called.
5.2.10 Const cast[expr.const.cast]
1
+------- BEGIN BOX 5 -------+
Editorial change from previous edition: it is permitted to use
const_cast as a no-op.
+------- END BOX 5 -------+
The result of the expression const_cast<T>(v) is of type "T." Types
shall not be defined in a const_cast. Conversions that can be per­
formed explicitly using const_cast are listed below. No other conver­
sion shall be performed explicitly using const_cast.
2 An rvalue of type "pointer to cv1T" can be explicitly converted to
the type "pointer to cv2T", where T is any object type and where cv1
and cv2 are cv-qualifications, using the cast const_cast<cv2T*>. An
lvalue of type cv1T can be explicitly converted to an lvalue of type
cv2T, where T is any object type and where cv1 and cv2 are cv-
qualifications, using the cast const_cast<cv2T&>. The result of a
pointer or reference const_cast refers to the original object.
3 An rvalue of type "pointer to member of X of type cv1T" can be
explicitly converted to the type "pointer to member of X of type cv2T", where T is a data member type and where cv1 and cv2 are cv-
qualifiers, using the cast const_cast<cv2T X::*>. The result of a
pointer to member const_cast will refer to the same member as the
original (uncast) pointer to data member.
4 The following rules define casting away constness. In these rules Tn
and Xn represent types. For two pointer types:
X1 is T1cv1,1 * ... cv1,N * where T1 is not a pointer type
X2 is T2cv2,1 * ... cv2,N * where T2 is not a pointer type
K is min(N,M)
casting from X1 to X2 casts away constness if, for a non-pointer type
T (e.g., int), there does not exist an implicit conversion from:
Tcv1,(N-K+1) * cv1,(N-K+2) * ... cv1,N *
to
Tcv2,(N-K+1) * cv2,(M-K+2) * ... cv2,M *
5 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.
6 Casting from an rvalue of type "pointer to data member of X of type
T1" to the type "pointer to data member of Y of type T2" casts away
constness if a cast from an rvalue of type "pointer to T1" to the type
"pointer to T2" casts away constness.
7 [Note: these rules are not intended to protect constness in all cases.
For instance, conversions between pointers to functions are not cov­
ered because such conversions lead to values whose use causes
undefined behavior. For the same reasons, conversions between point­
ers 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. For multi-level pointers to data members,
or multi-level mixed object and member pointers, the same rules apply
as for multi-level object pointers. That is, the "member of"
attribute is ignored for purposes of determining whether const has
been cast away.
8 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 constness may produce undefined behavior
(_dcl.type.cv_). ]
9 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.
5.3 Unary expressions[expr.unary]
1 Expressions with unary operators group right-to-left.
unary-expression:postfix-expression++unary-expression--unary-expressionunary-operator cast-expressionsizeofunary-expressionsizeof (type-id)new-expressiondelete-expressionunary-operator: one of
* & + - ! ~5.3.1 Unary operators[expr.unary.op]
1 The unary * operator means indirection: the expression shall be a
pointer, and the result is an lvalue referring to the object or func­
tion to which the expression points. If the type of the expression is
"pointer to T," the type of the result is "T."
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 "cvT" is
"pointer to cvT," with the same cv-qualifiers. [Example: the address
of an object of type "const int" has type "pointer to const int." ]
For a qualified-id, 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] For a static member of type "T", the type is plain
"pointer to T." [Note: a pointer to member is only formed when an
explicit & is used and its operand is a qualified-id not enclosed in
parentheses. [Example: the expression &(qualified-id), where the
qualified-id is enclosed in parentheses, does not form an expression
of type "pointer to member." ] Neither does qualified-id, because
there is no implicit conversion from the type "nonstatic member func­
tion" 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 &unqualified-id a pointer to member, even
within the scope of unqualified-id's class. ]
+------- BEGIN BOX 6 -------+
This section probably needs to take into account const and its rela­
tionship to mutable.
+------- END BOX 6 -------+
3 The address of an object of incomplete type can be taken, but if the
complete type of that object has the address-of operator (operator&())
overloaded, then the behavior is undefined (and no diagnostic is
required).
4 The address of an overloaded function (_over_) can be taken only in a
context that uniquely determines which version of the overloaded func­
tion is referred to (see _over.over_). [Note: since the context might
determine whether the operand is a static or nonstatic member func­
tion, the context can also affect whether the expression has type
"pointer to function" or "pointer to member function." ]
5 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.
6 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.
7 The operand of the logical negation operator ! is converted to bool
(_conv.bool_); its value is true if the converted operand is false and
false otherwise. The type of the result is bool.
8 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.
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 decremented analogously to the prefix ++
operator, except that the operand shall not be of type bool.
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. [Note:sizeof(char) is 1, but
sizeof(bool) and sizeof(wchar_t) are implementation-defined. 10) See
_intro.memory_ for the definition of byte and _basic.types_ for the
definition of object representation. ]
2 When applied to a reference, the result is the size of the referenced
object. When applied to a class, the result is the number of bytes in
an object of that class including any padding required for placing
such objects in an array. The size of any class or class object is
greater than zero. 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 sup­
pressed on the operand of sizeof.
5 Types shall not be defined in a sizeof expression.
6 The result is a constant of an implementation-defined type which is
the same type as that which is named size_t 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_) to which it is applied. This type shall be a complete
nonabstract object type or array type (_intro.object_, _basic.types_,
_class.abstract_).
_________________________
10) sizeof(bool) is not required to be 1.
new-expression:::optnewnew-placementopt new-type-id new-initializeropt::optnewnew-placementopt(type-id)new-initializeroptnew-placement:(expression-list)new-type-id:type-specifier-seq new-declaratoroptnew-declarator:*cv-qualifier-seqopt new-declaratoropt::opt nested-name-specifier*cv-qualifier-seqopt new-declaratoroptdirect-new-declaratordirect-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 an 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 in a new-expression is the longest possible sequence of
new-declarators. This prevents ambiguities between declarator opera­
tors &, *, [], and their expression counterparts. [Example: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 Parentheses shall not appear in a new-type-id used as the operand for
new.
4 [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). ]
5 The type-specifier-seq shall not contain class declarations, or enu­
meration declarations.
6 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]
return an int* and the type of new int[i][10] is int (*)[10]. ]
7 Every constant-expression in a direct-new-declarator shall be an inte­
gral constant expression (_expr.const_) with a strictly positive
value. The expression in a direct-new-declarator shall be of integral
type (_basic.fundamental_) with a non-negative value. [Example: 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-expression). If n is negative, the effect of new float[n][5] is unde­
fined. ]
8 When the value of the expression in a direct-new-declarator is zero,
an array with no elements is allocated. The pointer returned by the
new-expression is non-null and distinct from the pointer to any other
object.
9 Storage for the object created by a new-expression is obtained from
the appropriate allocation function (_basic.stc.dynamic.allocation_).
When the allocation function is called, the first argument will be
amount of space requested (which shall be no larger than the size of
the object being created unless that object is an array).
10An implementation shall provide default definitions of the global
allocation functions operator new() for non-arrays
(_basic.stc.dynamic_, _lib.new.delete.single_) and operator new[]()
for arrays (_lib.new.delete.array_). [Note: A C++ program can provide
alternative definitions of these functions
(_lib.replacement.functions_), and/or class-specific versions
(_class.free_). ]
11The new-placement syntax can be used to supply additional arguments to
an allocation function. If used, overloading resolution is done by
assembling an argument list from the amount of space requested (the
first argument) and the expressions in the new-placement part of the
new-expression (the second and succeeding arguments).
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,
implementation-defined values representing array allocation over­
head. They might vary from one use of new to another. ]
13The allocation function shall either return null or a pointer to a
block of storage in which the object shall be created. [Note: 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. ]
14If the type of the object created by the new-expression is T:
--If the new-initializer is omitted and T is a non-POD class type (or
array thereof), then if the default constructor for T is accessible
it is called, otherwise the program is ill-formed;
--If the new-initializer is omitted and T is a POD type (or array
thereof), then the object thus created has indeterminate value;
--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.
15Access and ambiguity control are done for both the allocation function
and the constructor (_class.ctor_, _class.free_).
16The allocation function can indicate failure by throwing a bad_alloc
exception (_except_, _lib.bad.alloc_). In this case no initialization
is done.
17If the constructor throws an exception and the new-expression does not
contain a new-placement, then the deallocation function
(_basic.stc.dynamic.deallocation_, _class.free_) is used 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.
18If the constructor throws an exception and the new-expression contains
a new-placement, a name lookup is performed on the name of operator
delete in the scope of this new-expression. If the lookup succeeds
and exactly one of the declarations found matches the declaration of
that placement operator new, then the matching placement operator
delete shall be called (_basic.stc.dynamic.deallocation_).
19A declaration of placement operator delete matches the declaration of
a placement operator new when it has the same number of parameters and
all parameter types except the first are identical disregarding top-
level cv-qualifiers.
20If placement operator delete is called, it is passed the same argu­
ments as were passed to placement operator new. If the implementation
is allowed to make a copy of an argument as part of the placement new
call, it is allowed to make a copy (of the same original value) as
part of the placement delete call, or to reuse the copy made as part
of the placement new call. If the copy is elided in one place, it
need not be elided in the other.
21The way the object was allocated determines how it is freed: if it is
allocated by ::new, then it is freed by ::delete, and if it is an
array, it is freed by delete[] or ::delete[] as appropriate.
+------- BEGIN BOX 7 -------+
This is a correction to San Diego resolution 3.5, which on its face
seems to require that whether to use delete or delete[] must be
decided purely on syntactic grounds. I believe the intent of the com­
mittee was to make the form of delete correspond to the form of the
corresponding new.
+------- END BOX 7 -------+
22Whether 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 throws an exception.
5.3.5 Delete[expr.delete]
1 The delete-expression operator destroys a complete object
(_intro.object_) or array created by a new-expression.
delete-expression:::optdeletecast-expression::optdelete [ ]cast-expression
The first alternative is for non-array objects, and the second is for
arrays. The operand shall have a pointer type. The result has type
void.
2 In either alternative, if the value of the operand of delete is the
null pointer the operation has no effect. Otherwise, in the first
alternative (delete object), the value of the operand of delete shall
be a pointer to a non-array object created by a new-expression without
a new-placement specification, or a pointer to a sub-object
(_intro.object_) representing a base class of such an object
(_class.derived_), or an expression of class type with a conversion
function to pointer type (_class.conv,fct_) which yields a pointer to
such an object. If not, the behavior is undefined. In the second
alternative (delete array), the value of the operand of delete shall
be a pointer to an array created by a new-expression without a new-placement specification. If not, the behavior is undefined.
3 In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, 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.11)
_________________________
11) This implies that an object cannot be deleted using a point of
4 It is unspecified whether the deletion of an object changes its value.
If the expression denoting the object in a delete-expression is a mod­
ifiable lvalue, any attempt to access its value after the deletion is
undefined (_basic.stc.dynamic.deallocation_).
5 If the object being deleted has incomplete class type at the point of
deletion and the class has a non-trivial destructor or an allocation
function 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 construction; see _class.base.init_).
7 To free the storage pointed to, the delete-expression will call a
deallocation function (_basic.stc.dynamic.deallocation_).
8 An implementation provides default definitions of the global dealloca­
tion 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_).
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. 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.
cast-expression:unary-expression(type-id)cast-expression
2 Types shall not be defined in casts.
3 Any type conversion not mentioned below and not explicitly defined by
the user (_class.conv_) is ill-formed.
4 The conversions performed by static_cast (_expr.static.cast_), rein­terpret_cast (_expr.reinterpret.cast_), const_cast
(_expr.const.cast_), or any sequence thereof, can be performed using
the cast notation of explicit type conversion. The same semantic
restrictions and behaviors apply. If a given conversion can be per­
formed using either static_cast or reinterpret_cast, the static_cast
interpretation is used.
_________________________
type void* because there are no objects of type void.
5 In addition to those conversions, a pointer to an object of a derived
class (_class.derived_) can be explicitly converted to a pointer to
any of its base classes regardless of accessibility restrictions
(_class.access.base_), provided the conversion is unambiguous
(_class.member.lookup_). The resulting pointer will refer to the con­
tained object of the base class.
5.5 Pointer-to-member operators[expr.mptr.oper]
1 The pointer-to-member operators ->* and .* group left-to-right.
pm-expression:cast-expressionpm-expression.*cast-expressionpm-expression->*cast-expression
2 The binary operator .* binds its second operand, which shall be of
type "pointer to member of T" 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" to its first operand, which shall be of
type "pointer to T" or "pointer to a class of which T is an unambigu­
ous and accessible base class." The result is an object or a function
of the type specified by the second operand.
4 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].
5 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-expressionmultiplicative-expression*pm-expressionmultiplicative-expression/pm-expressionmultiplicative-expression%pm-expression
2 The operands of * and / shall have arithmetic type; the operands of %
shall have integral type. The usual arithmetic conversions are per­
formed 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-defined.
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 type.
additive-expression:multiplicative-expressionadditive-expression+multiplicative-expressionadditive-expression-multiplicative-expression
For addition, either both operands shall have arithmetic type, or one
operand shall be a pointer to a completely defined object type and the
other shall have integral type.
2 For subtraction, one of the following shall hold:
--both operands have arithmetic type;
--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 type.
3 If both operands have arithmetic type, the usual arithmetic conver­
sions are performed on them. 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. If the result is used as an operand of the
unary * operator, the behavior is undefined unless both the pointer
operand and the result point to elements of the same array object, or
the pointer operand points one past the last element of an array
object and the result points to an element of the same array object.
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.12)
_________________________
12) Another way to approach pointer arithmetic is first to convert the
pointer(s) to character pointer(s): In this scheme the integral ex­
pression 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 character point­
ers is similarly divided by the size of the object originally 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.
5.8 Shift operators[expr.shift]
1 The shift operators << and >> group left-to-right.
shift-expression:additive-expressionshift-expression<<additive-expressionshift-expression>>additive-expression
The operands shall be of integral type and integral promotions are
performed. The type of the result is that of the promoted left
operand. The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the promoted left
operand. The value of E1 << E2 is E1 (interpreted as a bit pattern)
left-shifted E2 bits; vacated bits are zero-filled. The value of E1>> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned
type or has a nonnegative value, the vacated bits shall be zero-
filled. If E1 has a negative value, the behavior of the right shift
is implementation-defined.
5.9 Relational operators[expr.rel]
1 [Note: the relational operators group left-to-right, but this fact is
not very useful; a<b<c means (a<b)<c and not(a<b)&&(b<c). --endnote]
relational-expression:shift-expressionrelational-expression<shift-expressionrelational-expression>shift-expressionrelational-expression<=shift-expressionrelational-expression>=shift-expression
The operands shall have arithmetic or pointer type. The operators <
(less than), > (greater than), <= (less than or equal to), 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 arithmetic operands.
Pointer conversions are performed on pointer operands to bring them to
the same type, which shall be a cv-qualified or cv-unqualified version
of the type of one of the operands. [Note: this implies that any
pointer can be compared to an integral constant expression evaluating
to zero and any pointer can be compared to a pointer of cv-qualified
or cv-unqualified type void* (in the latter case the pointer is first
converted to void*). ] Pointers to objects or functions of the same
type (after pointer conversions) can be compared; the result depends
on the relative positions of the pointed-to objects or functions in
the address space as follows:
--If two pointers of the same type point to the same object or func­
tion, or both point one past the end of the same array, or are both
null, they compare equal.
--If two pointers of the same type point to different objects or func­
tions, or only one of them is null, they compare unequal.
--If two pointers point to nonstatic data members of the same object,
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 members of the same object sepa­
rated 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 implementation-defined.
3
+------- BEGIN BOX 8 -------+
This requires that an implementation not trap on any pointer compari­
son and may introduce an unacceptable runtime overhead. The ISO C
standard states that ``other'' pointer comparisons are undefined, not
implementation-defined. Should we be consistent with the ISO C stan­
dard?
+------- END BOX 8 -------+
5.10 Equality operators[expr.eq]
1 equality-expression:relational-expressionequality-expression==relational-expressionequality-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. ]
2 In addition, pointers to members of the same type can be compared.
Pointer to member conversions (_conv.mem_) are performed. A pointer
to member can be compared to an integral constant expression that
evaluates to zero. If one operand is a pointer to a virtual member
function and the other is not the null pointer to member value, the
result is unspecified.
5.11 Bitwise AND operator[expr.bit.and]
1 and-expression:equality-expressionand-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
operands.
5.12 Bitwise exclusive OR operator[expr.xor]
1 exclusive-or-expression:and-expressionexclusive-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 operands.
5.13 Bitwise inclusive OR operator[expr.or]
1 inclusive-or-expression:exclusive-or-expressioninclusive-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 operands.
5.14 Logical AND operator[expr.log.and]
1 logical-and-expression:inclusive-or-expressionlogical-and-expression&&inclusive-or-expression
The && operator groups left-to-right. The operands are both converted
to type bool (_conv.bool_). The result is true if both operands are
true and false otherwise. Unlike &, && guarantees left-to-right eval­
uation: 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-expressionlogical-or-expression||logical-and-expression
The || operator groups left-to-right. The operands are both converted
to bool (_conv.bool_). 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 evaluated 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-expressionlogical-or-expression?expression:assignment-expression
Conditional expressions group right-to-left. The first expression is
converted to bool (_conv.bool_). 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 temporaries
(_class.temporary_) happen before the second or third expression is
evaluated.
2 If either the second or third expression is a throw-expression
(_except.throw_), the result is of the type of the other.
3 If both the second and the third expressions are of arithmetic type,
then if they are of the same type the result is of that type; other­
wise the usual arithmetic conversions are performed to bring them to a
common type. Otherwise, if both the second and the third expressions
are either a pointer or an integral constant expression that evaluates
to zero, pointer conversions (_conv.ptr_) are performed to bring them
to a common type, which shall be a cv-qualified or cv-unqualified ver­
sion of the type of either the second or the third expression. Other­
wise, if both the second and the third expressions are either a
pointer to member or an integral constant expression that evaluates to
zero, pointer to member conversions (_conv.mem_) are performed to
bring them to a common type13) which shall be a cv-qualified or cv-
unqualified version of the type of either the second or the third
expression. Otherwise, if both the second and the third expressions
are lvalues of related class types, they are converted to a common
type (which shall be a cv-qualified or cv-unqualified version of the
type of either the second third expression) as if by a cast to a ref­
erence to the common type (_expr.static.cast_). Otherwise, if both
the second and the third expressions are of the same class T, the com­
mon type is T. Otherwise, if both the second and the third expres­
sions have type "cvvoid", the common type is "cvvoid." Otherwise the
expression is ill formed. The result has the common type; only one of
the second and third expressions is evaluated. The result is an
lvalue if the second and the third operands are of the same type and
both are lvalues.
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.
_________________________
13) This is one instance in which the "composite type", as described
in the C Standard, is still employed in C++.
assignment-expression:conditional-expressionunary-expression assignment-operator assignment-expressionthrow-expressionassignment-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 converted
to the cv-unqualified type of the left operand using standard conver­
sions (_conv_) and/or user-defined conversions (_class.conv_), as nec­
essary.
4 Assignment to objects of a class (_class_) X is defined by the func­
tion X::operator=() (_over.ass_). Unless the user defines an
X::operator=(), the default version is used for assignment
(_class.copy_). This implies that an object of a class derived from X
(directly or indirectly) by unambiguous public derivation
(_class.derived_) can be assigned to an X.
5 For class objects, assignment is not in general the same as initial­
ization (_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 E1op= E2 is equivalent to
E1=E1opE2 except that E1 is evaluated only once. E1 shall not have
bool type. In += and -=, E1 shall either have arithmetic type or be a
pointer to a possibly-qualified completely defined object type. In
all other cases, E1 shall have arithmetic type.
8 See _except.throw_ for throw expressions.
5.18 Comma operator[expr.comma]
1 The comma operator groups left-to-right.
expression:assignment-expressionexpression,assignment-expression
A pair of expressions separated by a comma is evaluated left-to-right
and the value of the left expression is discarded. All side effects
of the left expression 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 this clause 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_), and as member
constant initializers (_class.static.data_).
constant-expression:conditional-expression
An integral constant-expression can involve only literals
(_lex.literal_), enumerators, const values of integral or enumeration
types initialized with constant expressions (_dcl.init_), 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,
--an address constant expression for an 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 or a function. The pointer shall
be created explicitly, using the unary & operator, or implicitly using
an expression of array (_conv.array_) or function (_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. An expression that designates
the address of a member or base class of a non-POD class object
(_class_) is not an address constant expression (_class.cdtor_).
Function calls shall not be used in an address constant expression,
even if the function is inline and has a reference return type.
5 A pointer to member constant expression shall be created using the
unary & operator applied to a qualified-id operand (_expr.unary.op_).