______________________________________________________________________

  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 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]
  _________________________
  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:
                  literal
                  this
                  :: 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-id
                  qualified-id

          unqualified-id:
                  identifier
                  operator-function-id
                  conversion-function-id
                  ~ class-name
                  template-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-specifier templateopt 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-expression
                  postfix-expression [ expression ]
                  postfix-expression ( expression-listopt )
                  simple-type-specifier ( expression-listopt )
                  postfix-expression . templateopt id-expression
                  postfix-expression -> templateopt 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 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 vq1
    X", and the type of E2 is "cq2 vq2 T", the expression designates the
    named  member  of the object designated by the first expression.  If
    E1 is an lvalue, then E1.E2 is an lvalue.   Let  the  notation  vq12
    stand  for  the  "union"  of vq1 and vq2 ; that is, if vq1 or vq2 is
    volatile, then vq12 is volatile.  Similarly, let the  notation  cq12
    stand  for  the  "union"  of  cq1 and cq2; that is, if cq1 or cq2 is
    const, then cq12 is const.  If E2 is declared to be a  mutable  mem­
    ber,  then  the type of E1.E2 is "vq12 T".  If E2 is not declared to
    be a mutable member, then the type of E1.E2 is "cq12 vq12 T".

  --If E2 is a (possibly overloaded) 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 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 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 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 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 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 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 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
  _________________________
  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 cv void." 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 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­
  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 cv1 T" can be  explicitly  converted  to
  the  type "pointer to cv2 T", where T is any object 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 converted 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 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-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,  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  "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 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:
                  ::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:
                  * cv-qualifier-seqopt new-declaratoropt
                   ::opt nested-name-specifier * cv-qualifier-seqopt new-declaratoropt
                  direct-new-declarator
          direct-new-declarator:
                  [ expression ]
                  direct-new-declarator [ constant-expression ]
          new-initializer:
                  ( expression-listopt )
  Entities  created  by  a  new-expression have dynamic storage duration
  (_basic.stc.dynamic_).  [Note: the lifetime of such an entity  is  not
  necessarily  restricted to the scope in which it is created.  ] If the
  entity is 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:
                  ::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 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-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 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-expression
                  additive-expression + multiplicative-expression
                  additive-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-expression
                  shift-expression << additive-expression
                  shift-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).     --end
  note]
          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 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-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 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-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

  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 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 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 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-expression
                  logical-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-expression
                  logical-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 "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.  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-expression
                  unary-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 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 E1 op= E2 is  equivalent  to
  E1=E1 op  E2 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-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
  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_).