______________________________________________________________________

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_), and are not  guaranteed  for  operands  of  type  bool.
[Example: the left operand of += must not have type bool.  ] ]

3 This clause defines the operators when applied to types for which they
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 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 undefined
i = 7,i++,i++;   // `i' becomes 9

i = ++i + 1;     // the behavior is undefined
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.  [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.

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.  [Note: 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 conversions 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, 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.1)

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

12The  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.2)

5.1  Primary expressions                                   [expr.prim]

1 Primary  expressions  are  literals, names, and names qualified by the
scope resolution operator ::.
primary-expression:
literal
this
:: identifier
:: operator-function-id
:: qualified-id
( expression )
id-expression

id-expression:
unqualified-id
qualified-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
_________________________
1)  As a consequence, operands of type bool, wchar_t, or an enumerated
type are converted to some integral type.
2) The cast and assignment operators must still perform their specific
conversions as described in _expr.cast_, _expr.static.cast_  and  _ex­
pr.ass_.

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.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.

6 An id-expression is a restricted form of a primary-expression.  [Note:
an id-expression can appear after . and -> operators (_expr.ref_).  ]
id-expression:
unqualified-id
qualified-id

unqualified-id:
identifier
operator-function-id
conversion-function-id
~ class-name
template-id

+-------                 BEGIN BOX 2                -------+
Issue: now it's allowed to  invoke  ~int(),  but  ~class-name  doesn't
allow for that.
+-------                  END BOX 2                 -------+

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-specifier templateopt unqualified-id
nested-name-specifier:
class-or-namespace-name :: nested-name-specifieropt

class-or-namespace-name:
class-name
namespace-name
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

qualified-id; _class.qual_ describes name look up  for  class  members
that  appear  in  qualified-ids.  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.  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; _namespace.qual_ describes name look up for namespace
members that appear in qualified-ids.  The type of the qualified-id is
the  type  of the member.  The result is the member.  The result is an
lvalue if the member is.

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 member func­
tion 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
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-expression
postfix-expression [ expression ]
postfix-expression ( expression-listopt )
simple-type-specifier ( expression-listopt )
postfix-expression . templateopt ::opt id-expression
postfix-expression -> templateopt ::opt id-expression
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

5.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 a completely-defined
object type.  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 function3) (_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 shall have pointer  or  reference  to  a  function
type.   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 appropriate function shall be selected according to the rules
_________________________
3)  A static member function (_class.static_) is an ordinary function.

in  _over.match_.   The  function  called in a member function call is
normally selected according to the static type of the  object  expres­
sion  (see _class.derived_), but if that function is virtual the func­
tion 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 a complete object type, a reference type or the type void.

3 When a function is called, each parameter (_dcl.fct_)  shall  be  ini­
tialized (_dcl.init_, _class.copy_, _class.ctor_) with its correspond­
ing argument.  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 over­
rider is converted to the return type of the statically  chosen  func­
tion.

4 [Note: a function can change the values of its nonconstant parameters,
but these changes cannot affect the values  of  the  arguments  except
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 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 (_class_), the behavior is undefined.  If the argument has
integral or enumeration type that is subject to  the  integral  promo­
tions  (_conv.prom_),  or a floating point type that is subject to the
floating point promotion (_conv.fpprom_), the value of the argument is

converted  to the promoted type before the call.  These promotions are
referred to as the default argument promotions.

8 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.

9 The  function-to-pointer  standard  conversion  (_conv.func_)  is sup­
pressed on the postfix expression of a function call.

10Recursive calls are permitted.

11A 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 declara­
tion 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;4) 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
_________________________
4) 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.

(_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)5).

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: because the name of a class is inserted  in
its  class  scope  (_class_), the name of a class is also considered a
nested 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   contains   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
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 vq1
_________________________
5)  Note that if E1 has the type "pointer to class X", then (*(E1)) is
an lvalue.

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) 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 3                -------+
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 3                 -------+

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,
see annex _depr_.  ] 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 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 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 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 unique6) 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 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 pointed (referred) to by v, the result is
_________________________
6) The complete object pointed or referred to by v can contain other B
objects as base classes, but these are ignored.

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
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);  // succeeds
ap = dynamic_cast<A*>(bp);       // succeeds
bp = dynamic_cast<B*>(ap);       // fails
ap = dynamic_cast<A*>(&dr);      // succeeds
bp = 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 A
D*  dp = dynamic_cast<D*>(ap);  // fails: ambiguous
E*  ep = (E*)ap;  // error: cast from virtual base
E*  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  an  lvalue  of  type
const type_info.   The   lvalue   refers   to   a   type_info   object
(_lib.type.info_)  that  represents  the  type-id  or  the type of the
expression respectively.

2 If the expression is an lvalue of 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,7) then the pointer shall either be  a  null  pointer
value  (_conv.ptr_)  or  point to a valid object.  If the pointer is a
_________________________
7)  If  p is a pointer, then *p, (*p), ((*p)), and so on all meet this
requirement.

null pointer value, the typeid expression throws the bad_typeid excep­
tion  (_lib.bad.typeid_).  Otherwise, the result of the typeid expres­
sion 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,8) 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 true
typeid(D)  == typeid(const D); // yields true
typeid(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
cast away constness.  See _expr.const.cast_.

2 If the expression v can be implicitly converted (_conv_)  to  type  T,
then  the  result  of static_cast<T>(v) is the result of that implicit
conversion.

+-------                 BEGIN BOX 4                -------+
This needs to  say  that  explicit  constructors  are  considered  for
explicit casts.
+-------                  END BOX 4                 -------+

3 If  the  static_cast does not correspond to an implicit conversion, it
shall perform one of the conversions listed below.  No  other  conver­
sion can be performed explicitly using a static_cast.

_________________________
8) 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.

4 Any  expression  can  be  explicitly  converted to type cv void."  The

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 (_class.derived_)
from B, if a valid standard conversion from  "pointer  to  cv2  D"  to
"pointer   to  cv2  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 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  (_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 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 (_class.derived_) from B, if a valid standard conversion  from
"pointer  to  cv2 D" to "pointer to cv2 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 (_class.derived_) of D, if  a  valid  standard
conversion  from "pointer to member of B of type cv2 T" to "pointer to
member of D of type cv2 T" 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­
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  object  types.   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.

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
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
copy is made, and constructors (_class.ctor_) or conversion  functions
(_class.conv_) are not called.

5.2.10  Const cast                                   [expr.const.cast]

1 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 cv1 T" can be  explicitly  converted  to
the  type  "pointer  to cv2 T", where T is any object type or the void
type and, where cv1 and cv2  are  cv-qualifications,  using  the  cast
const_cast<cv2  T*>.   An  lvalue of type cv1 T can be explicitly con­
verted to an lvalue of type cv2 T, where T  is  any  object  type  and
where cv1 and cv2 are cv-qualifications, using the cast const_cast<cv2
T&>.  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 cv1 T" can be
explicitly converted to the type "pointer to member of X of  type  cv2

T",  where  T  is  a  data  member  type and where cv1 and cv2 are cv-
qualifiers, using the cast const_cast<cv2 T 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 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 [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 constness9) may produce undefined behavior
(_dcl.type.cv_).  ]

6 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,M *   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,(M-K+1) * cv2,(M-K+2) * ... cv2,M *

7 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.

8 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.

9 [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  unde­
fined 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.  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.
]

_________________________
9) const_cast is not limited to conversions that cast away  constness.

5.3  Unary expressions                                    [expr.unary]

1 Expressions with unary operators group right-to-left.
unary-expression:
postfix-expression
++  unary-expression
--  unary-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 means indirection:  the  expression  shall  be  a
pointer to a complete 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 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 "cv T" is
"pointer to cv T," 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 static member of type "T",  the
type  of  the result is plain "pointer to T."  If the member is a non­
static 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]

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 the type "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  &unqualified-id  a
pointer  to  member,  even  within  the  scope of the unqualified-id's
class.  ]

+-------                      BEGIN BOX 5                     -------+
This section probably needs to take into account const and  its  rela­
tionship to mutable.
+-------                       END BOX 5                      -------+

4 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).  The operator & shall not be a bit-field.

5 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."  ]

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 (_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.

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
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.  sizeof(char) is 1; the result of sizeof
applied to any other fundamental type (_basic.fundamental_) is  imple­
mentation-defined.     [Note:    in   particular,   sizeof(bool)   and
sizeof(wchar_t)   are   implementation-defined.10)   ]   [Note:    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
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
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_).  [Note: because, references are not objects, refer­
ences cannot be created by new-expressions.  ]
new-expression:
::opt new new-placementopt new-type-id new-initializeropt
::opt new new-placementopt ( type-id ) new-initializeropt
new-placement:
( expression-list )
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 )
_________________________
10) sizeof(bool) is not required to be 1.

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.
]

+-------                      BEGIN BOX 6                     -------+
Change: During the editorial session after the Monterey meeting, folks
doing editorial work decided to change the syntax of a  new-expression
to  allow operator & in a new-declarator.  They decided to instead add
to the semantic rules of the language  (see  paragraph  1  above)  the
restriction  that reference types cannot be newed.  Like this, expres­
sions of the form new int*i; and new int&i; parse the same and  gener­
ate  the same syntax error.  Otherwise, the expression new int&i; will
parse as (new int)&i; and if i is an int, the expression will actually
be valid.  This would be very surprising for users.
+-------                       END BOX 6                      -------+

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,
the allocation function is called to allocate an array  with  no  ele­
ments.   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 the
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_).  ] When the keyword new in a  new-expression  is  pre­
ceeded  by  the  unary  :: operator, the global allocation function is
used to allocate the storage.

11The new-placement syntax can be used to supply additional arguments to
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
(_class_) (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
(_basic.types_), 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  exits  using 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 exits using 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 decla­
ration 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 exits using an  exception.

23The  deallocation function to be used to free memory shall be accessi­
ble and not ambiguous.

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:
::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.  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  the  first  element  of an array created by a new-
expression without a new-placement specification.  If not, the  behav­
ior 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 be a
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.11)
[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.  ]

4 The cast-expression in a delete-expression shall be evaluated  exactly
once.

+-------                      BEGIN BOX 8                     -------+
Change: See email message core-6090.
+-------                       END BOX 8                      -------+

It is unspecified whether the deletion of an object changes its value.
If the expression denoting the object  is  a  modifiable  lvalue,  any
attempt  to  access  its  value  after  the  completion of the delete-
expression is undefined (_basic.stc.dynamic.deallocation_).

+-------                      BEGIN BOX 9                     -------+
Change: the phrase 'after the  completion  of  the  delete-expression'
replaces  the  phrase  'after  the deletion' to make it clear at which
point the behavior becomes undefined.  See email message core-6101.
+-------                       END BOX 9                      -------+

[Note: a pointer to a const type can  be  the  operand  of  a  delete-
expression.  ]

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_).  When the keyword delete in  a
delete-expression  is  preceeded  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_).
_________________________
11) This implies that an object cannot be deleted using a  pointer  of
type void* because there are no objects of type void.

5.4  Explicit type conversion (cast notation)              [expr.cast]

1 The  result  of the expression (T) cast-expression is of type T.  If T
is a reference type, the result is an lvalue of the type referenced by
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.

5 In addition to those conversions, a pointer to an object of a  derived
class  (or  an  lvalue of derived class type) (_class.derived_) can be
explicitly converted to a pointer (a reference) to  any  of  its  base
classes       regardless       of      accessibility      restrictions
(_class.access.base_),  provided   the   conversion   is   unambiguous
(_class.member.lookup_).  The resulting pointer (reference) will refer
to the base class subobject of the object of derived class type.

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" 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-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-defined.

1 The  additive operators + and - group left-to-right.  The usual arith­
metic conversions are performed for operands of arithmetic type.
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;

--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.

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)

5.8  Shift operators                                      [expr.shift]

1 The shift operators << and >> group left-to-right.
shift-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.

_________________________
12) 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
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.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 or  enumeration  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 operands of arith­
metic or enumeration  type.   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 a
null pointer constant 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  implicitly  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 10                     -------+
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 10                      -------+

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.  ]

2 In  addition,  pointers to members can be compared.  Pointer to member
conversions (_conv.mem_) are performed 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  to  member
can be compared to an integral constant expression evaluating to zero.
] 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 function, the result  is  unspecified.   Otherwise
they  compare equal if and only if they would refer to the same member
of the same complete object or the same subobject if they were  deref­
erenced  with  a  hypothetical  object  of  the associated class type.
[Example:
struct B {
void 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  (_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  (_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 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-expression
logical-or-expression ? expression : assignment-expression
Conditional expressions group right-to-left.  The first expression  is
implicitly  converted  to bool (_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  temporaries
(_class.temporary_)  happen  before  the second or third expression is
evaluated.

2 If the second and the third operands are lvalues  and  have  the  same
type  (before  any  implicit  conversions), the result is an lvalue of
that  type.   Otherwise,  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.  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 or enu­
meration type, then if they are of the same type the result is of that
type; otherwise 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  a  null  pointer  constant,
pointer conversions (_conv.ptr_) are performed to bring them to a com­
mon type, 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 either a pointer to mem­
ber  or  a  null  pointer  constant,  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  implicitly converted to a common type (which shall be a cv-
qualified or cv-unqualified version of the type of either  the  second
or third expression) as if by a cast to a reference to the common type
(_expr.static.cast_).  Otherwise, if both the  second  and  the  third
expressions are of the same class T, the common type is T.  Otherwise,
if both the second and the third expressions have type "cv void",  the
common  type  is  "cv  void."  Otherwise the expression is ill formed.
The result has the common type; only  one  of  the  second  and  third
expressions is evaluated.

_________________________
13) This is one instance in which the "composite type",  as  described
in the C Standard, is still employed in C++.

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 (_conv_) to the cv-unqualified type of the left operand.

4 Assignment to objects of a class (_class_) X is defined by  the  func­
tion X::operator=() (_over.ass_).  Unless X::operator=() is explicitly
declared in the class  member-specification,  the  implicitly-declared
default  assignment  operator  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 E1 op= E2 is equivalent to
E1=E1 op E2 except that E1 is evaluated only once.  In += and  -=,  E1
shall  either have arithmetic or enumeration type or be a pointer to a
possibly cv-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-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.  All  side  effects
(_intro.execution_) of the left expression, except for the destruction
of  temporaries  (_class.temporary_),   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_), as static mem­
ber initializers (_class.static.data_), and as integral non-type  tem­
plate arguments (_temp.arg_).
constant-expression:
conditional-expression
An    integral   constant-expression   can   involve   only   literals
(_lex.literal_), enumerators, const variables or static  data  members
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 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_).