      ______________________________________________________________________

      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_) or enumeration type  (_dcl.enum_).
      Uses  of  overloaded  operators are transformed into function calls as
      described in _over.oper_.  Overloaded operators  obey  the  rules  for
      syntax specified in this clause, but the requirements of operand type,
      lvalue, and evaluation order are replaced by the  rules  for  function
      call.   Relations between operators, such as ++a meaning a+=1, are not
      guaranteed for overloaded operators (_over.oper_), and are not guaran-
      teed for operands of type bool.   --end note]

    3 This clause defines the effects of operators when applied to types for
      which they have not been overloaded.  Operator overloading  shall  not
      modify  the  rules  for the built-in operators, that is, for operators
      applied to types for which they are defined by  this  Standard.   How-
      ever, these built-in operators participate in overload resolution; see
      _over.match.oper_.

    4 Except where noted, the order of evaluation of operands of  individual
      operators  and subexpressions of individual expressions, and the order
      in which side effects take place, is unspecified.  Between the  previ-
      ous  and  next  sequence  point  a scalar object shall have its stored
      value modified at most once by the evaluation of an expression.   Fur-
      thermore,  the  prior  value  shall  be accessed only to determine the
      value to be stored.  The requirements of this paragraph shall  be  met
      for  each  allowable  ordering of the subexpressions of a full expres-
      sion; otherwise the behavior is undefined.  [Example:
              i = v[i++];      // the behavior is undefined
              i = 7, i++, i++; // `i' becomes 9

              i = ++i + 1;     // the behavior is undefined
              i = i + 1;       // the value of 'i' is incremented
       --end example]

    5 If during the evaluation of an expression, the result is not mathemat-
      ically  defined  or  not  in the range of representable values for its
      type, the behavior is undefined, unless such an expression is  a  con-
      stant  expression  (_expr.const_),  in  which case the program is ill-
      formed.  [Note: most existing implementations of  C++  ignore  integer

      overflows.  Treatment of division by zero, forming a remainder using a
      zero divisor, and all floating point exceptions vary  among  machines,
      and is usually adjustable by a library function.  ]

    6 If  an  expression initially has the type "reference to T" (_dcl.ref_,
      _dcl.init.ref_), the type is adjusted to T" prior to any further anal-
      ysis,  the expression designates the object or function denoted by the
      reference, and the expression is an lvalue.

    7 An expression designating an object is called an object-expression.

    8 Whenever an lvalue expression appears as an  operand  of  an  operator
      that   expects  an  rvalue  for  that  operand,  the  lvalue-to-rvalue
      (_conv.lval_), array-to-pointer (_conv.array_), or function-to-pointer
      (_conv.func_)  standard conversions are applied to convert the expres-
      sion to an rvalue.  [Note: because cv-qualifiers are removed from  the
      type  of  an  expression of non-class type when the expression is con-
      verted to an rvalue, an lvalue expression of type const int  can,  for
      example,  be  used where an rvalue expression of type int is required.
      ]

    9 Many binary operators that expect operands of arithmetic  or  enumera-
      tion  type  cause conversions and yield result types in a similar way.
      The purpose is to yield a common type, which is also the type  of  the
      result.   This  pattern  is  called  the usual arithmetic conversions,
      which are defined as follows:

      --If either operand is of type long double, the other  shall  be  con-
        verted to long double.

      --Otherwise, if either operand is double, the other shall be converted
        to double.

      --Otherwise, if either operand is float, the other shall be  converted
        to float.

      --Otherwise,  the integral promotions (_conv.prom_) shall be performed
        on both operands.1)

      --Then,  if  either  operand  is unsigned long the other shall be con-
        verted to unsigned long.

      --Otherwise, if one operand is a long int and the other unsigned  int,
        then  if a long int can represent all the values of an unsigned int,
        the unsigned int shall be converted to a long  int;  otherwise  both
        operands shall be converted to unsigned long int.

      --Otherwise,  if  either operand is long, the other shall be converted
        to long.

      _________________________
      1) As a consequence, operands of type bool, wchar_t, or an  enumerated
      type are converted to some integral type.

      --Otherwise, if either operand is unsigned, the other  shall  be  con-
        verted to unsigned.

      [Note:  otherwise,  the  only remaining case is that both operands are
      int ]

    10The values of the  floating  operands  and  the  results  of  floating
      expressions  may  be  represented  in greater precision and range than
      that required by the type; the types are not changed thereby.2)

      5.1  Primary expressions                                   [expr.prim]

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

              id-expression:
                      unqualified-id
                      qualified-id

    2 A  literal  is  a  primary  expression.   Its type depends on its form
      (_lex.literal_).  A string literal is an lvalue;  all  other  literals
      are rvalues.

    3 The  keyword  this names a pointer to the object for which a nonstatic
      member function (_class.this_) is invoked.  The keyword this shall  be
      used only inside a nonstatic class member function body (_class.mfct_)
      or in a constructor mem-initializer (_class.base.init_).  The type  of
      the  expression  is  a pointer to the function's class (_class.this_),
      possibly with cv-qualifiers on the class type.  The expression  is  an
      rvalue.

    4 The operator :: followed by an identifier, a qualified-id, or an oper-
      ator-function-id is a primary-expression.  Its type  is  specified  by
      the declaration of the identifier, qualified-id, or operator-function-
      id.  The result is the entity denoted by the identifier, qualified-id,
      or  operator-function-id.   The result is an lvalue if the entity is a
      function or variable.  The identifier, qualified-id, or operator-func-
      tion-id  shall  have  global  namespace  scope or be visible in global
      scope because of a using-directive (_namespace.udir_).  [Note: the use
      of :: allows a type, an object, a function, an enumerator, or a names-
      pace declared in the global namespace to be referred to  even  if  its
      _________________________
      2) The cast and assignment operators must still perform their specific
      conversions  as  described in _expr.cast_, _expr.static.cast_ and _ex-
      pr.ass_.

      identifier has been hidden (_basic.lookup.qual_).  ]

    5 A  parenthesized  expression  is  a  primary expression whose type and
      value are identical to those of the enclosed expression.  The presence
      of  parentheses  does  not affect whether the expression is an lvalue.
      The parenthesized expression can be used in exactly the same  contexts
      as  those where the enclosed expression can be used, and with the same
      meaning, except as otherwise indicated.

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

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

    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_; for
      template-ids, see _temp.names_.  A class-name prefixed by ~ denotes  a
      destructor;  see  _class.dtor_.   Within the definition of a nonstatic
      member function, an identifier that names a nonstatic member is trans-
      formed  to  a class member access expression (_class.mfct.nonstatic_).
      ] The type of the expression is  the  type  of  the  identifier.   The
      result  is  the  entity  denoted  by the identifier.  The result is an
      lvalue if the entity is a function, variable, or data member.

    8         qualified-id:
                      nested-name-specifier templateopt unqualified-id
              nested-name-specifier:
                      class-or-namespace-name :: nested-name-specifieropt

              class-or-namespace-name:
                      class-name
                      namespace-name
      A nested-name-specifier that names a class, optionally followed by the
      keyword  template (_temp.arg.explicit_), and then followed by the name
      of a member of either that class (_class.mem_)  or  one  of  its  base
      classes  (_class.derived_),  is a qualified-id; _class.qual_ describes
      name look up for class members  that  appear  in  qualified-ids.   The
      result  is the member.  The type of the result is the type of the mem-
      ber.  The result is an lvalue if the member is a static  member  func-
      tion or a data member.  [Note: a class member can be referred to using
      a   qualified-id   at   any   point    in    its    potential    scope
      (_basic.scope.class_).   ] Where class-name :: class-name is used, and
      the two class-names refer to the same class, this notation  names  the
      constructor (_class.ctor_).  Where class-name :: ~ class-name is used,
      the two class-names shall refer to the same class; this notation names

      the  destructor  (_class.dtor_).   [Note:  a typedef-name that names a
      class is a class-name (_dcl.typedef_).  Except as  the  identifier  in
      the declarator for a constructor or destructor definition outside of a
      class member-specification (_class.ctor_,  _class.dtor_),  a  typedef-
      name  that  names  a class may be used in a qualified-id to refer to a
      constructor or destructor.  ]

    9 A nested-name-specifier that names  a  namespace  (_basic.namespace_),
      followed  by  the name of a member of that namespace (or the name of a
      member of a namespace made visible by a using-directive ) is a  quali-
      fied-id; _namespace.qual_ describes name look up for namespace members
      that appear in qualified-ids.  The result is the member.  The type  of
      the  result is the type of the member.  The result is an lvalue if the
      member is a function or a variable.

    10In a qualified-id, if the id-expression is  a  conversion-function-id,
      its  conversion-type-id shall denote the same type in both the context
      in which the entire qualified-id occurs and  in  the  context  of  the
      class denoted by the nested-name-specifier.

    11An  id-expression  that  denotes  a nonstatic data member or nonstatic
      member function of a class can only be used:

      --as part of a class member access (_expr.ref_) in which  the  object-
        expression refers to the member's class or a class derived from that
        class, or

      --to form a pointer to member (_expr.unary.op_), or

      --in the body of a nonstatic member function of that  class  or  of  a
        class derived from that class (_class.mfct.nonstatic_), or

      --in a mem-initializer for a constructor for that class or for a class
        derived from that class (_class.base.init_).

    12A template-id shall be used as an unqualified-id only as specified  in
      clauses _temp.explicit_, _temp.spec_, and _temp.class.spec_.

      5.2  Postfix expressions                                   [expr.post]

    1 Postfix expressions group left-to-right.

              postfix-expression:
                      primary-expression
                      postfix-expression [ expression ]
                      postfix-expression ( expression-listopt )
                      simple-type-specifier ( expression-listopt )
                      postfix-expression . templateopt ::opt id-expression
                      postfix-expression -> templateopt ::opt id-expression
                      postfix-expression . pseudo-destructor-name
                      postfix-expression -> pseudo-destructor-name
                      postfix-expression ++
                      postfix-expression --
                      dynamic_cast < type-id > ( expression )
                      static_cast < type-id > ( expression )
                      reinterpret_cast < type-id > ( expression )
                      const_cast < type-id > ( expression )
                      typeid ( expression )
                      typeid ( type-id )
              expression-list:
                      assignment-expression
                      expression-list , assignment-expression
              pseudo-destructor-name:
                      ::opt nested-name-specifieropt type-name :: ~ type-name
                      ::opt nested-name-specifieropt ~ type-name

      5.2.1  Subscripting                                         [expr.sub]

    1 A postfix expression followed by an expression in square brackets is a
      postfix expression.  One  of  the  expressions  shall  have  the  type
      "pointer  to T" and the other shall have enumeration or integral type.
      The result is an lvalue of type "T."  The type "T"  shall  be  a  com-
      pletely-defined object type.3) 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 an ordinary function call, the postfix expression shall
      be either an lvalue that refers to a function (in which case the func-
      tion-to-pointer standard conversion (_conv.func_) is suppressed on the
      postfix expression), or it shall have pointer to function type.  Call-
      ing  a  function  through an expression whose function type has a lan-
      guage linkage that is different from the language linkage of the func-
      tion   type   of   the   called  function's  definition  is  undefined
      (_dcl.link_).  For a member  function  call,  the  postfix  expression
      shall  be  an  implicit  (_class.mfct.nonstatic_,  _class.static_)  or
      _________________________
      3)  This is true even if the subscript operator is used in the follow-
      ing common idiom: &x[0].
      4)  A static member function (_class.static_) is an ordinary function.

      explicit class member access (_expr.ref_)  whose  id-expression  is  a
      function    member    name,    or   a   pointer-to-member   expression
      (_expr.mptr.oper_) selecting a function member.  The first  expression
      in  the  postfix  expression is then called the object expression, and
      the call is as a member of the object pointed to or referred  to.   In
      the case of an implicit class member access, the implied object is the
      one pointed to by this.  [Note: a member function call of the form f()
      is  interpreted  as  (*this).f() (see _class.mfct.nonstatic_).  ] If a
      function or member function name is used, the name can  be  overloaded
      (_over_),  in  which  case  the appropriate function shall be selected
      according to the rules in _over.match_.  The function called in a mem-
      ber function call is normally selected according to the static type of
      the object expression (see _class.derived_), but if that  function  is
      virtual  and  is  not specified using a qualified-id then the function
      actually called will be the final overrider (_class.virtual_)  of  the
      selected  function in the dynamic type of the object expression [Note:
      the dynamic type is the type of the object pointed or referred  to  by
      the  current  value  of  the  object expression.  Clause _class.cdtor_
      describes the behavior of virtual  function  calls  when  the  object-
      expression refers to an object under construction or destruction.  ]

    2 If  no declaration of the called function is visible from the scope of
      the call the program is ill-formed.

    3 The type of the function call expression is the  return  type  of  the
      statically  chosen function (i.e., ignoring the virtual keyword), even
      if the type of the function actually called is different.   This  type
      shall be a complete object type, a reference type or the type void.

    4 When  a  function  is called, each parameter (_dcl.fct_) shall be ini-
      tialized (_dcl.init_, _class.copy_, _class.ctor_) with its correspond-
      ing  argument.   When  a  function is called, the parameters that have
      object type shall have completely-defined object  type.   [Note:  this
      still allows a parameter to be a pointer or reference to an incomplete
      class type.  However, it prevents a passed-by-value parameter to  have
      an incomplete class type.  ] During the initialization of a parameter,
      an implementation may avoid the construction of extra  temporaries  by
      combining  the  conversions on the associated argument and/or the con-
      struction of temporaries with the initialization of the parameter (see
      _class.temporary_).   The  lifetime of a parameter ends when the func-
      tion in which it is defined returns.  The initialization and  destruc-
      tion  of each parameter occurs within the context of the calling func-
      tion.  [Example: the access of the constructor,  conversion  functions
      or destructor is checked at the point of call in the calling function.
      If a constructor or destructor for  a  function  parameter  throws  an
      exception, the search for a handler starts in the scope of the calling
      function; in particular, if the function called  has  a  function-try-
      block  (_except_) with a handler that could handle the exception, this
      handler is not considered.  ] The value of  a  function  call  is  the
      value  returned  by  the  called function except in a virtual function
      call if the return type of the final overrider is different  from  the
      return type of the statically chosen function, the value returned from
      the final overrider is converted to the return type of the  statically
      chosen function.

    5 [Note:  a  function can change the values of its non-const parameters,
      but these changes cannot affect the values  of  the  arguments  except
      where a parameter is of a reference type (_dcl.ref_); if the reference
      is to a const-qualified type, const_cast is required  to  be  used  to
      cast  away  the  constness  in  order  to modify the argument's value.
      Where a parameter is of const reference type  a  temporary  object  is
      introduced   if   needed   (_dcl.type_,  _lex.literal_,  _lex.string_,
      _dcl.array_, _class.temporary_).  In addition, it is possible to  mod-
      ify the values of nonconstant objects through pointer parameters.  ]

    6 A  function  can  be  declared to accept fewer arguments (by declaring
      default arguments (_dcl.fct.default_)) or more arguments (by using the
      ellipsis,  ...   _dcl.fct_) than the number of parameters in the func-
      tion definition (_dcl.fct.def_).  [Note:  this  implies  that,  except
      where  the  ellipsis (...)  is used, a parameter is available for each
      argument.  ]

    7 When there is no parameter for  a  given  argument,  the  argument  is
      passed  in such a way that the receiving function can obtain the value
      of the  argument  by  invoking  va_arg  (_lib.support.runtime_).   The
      lvalue-to-rvalue  (_conv.lval_),  array-to-pointer (_conv.array_), and
      function-to-pointer (_conv.func_) standard conversions  are  performed
      on  the argument expression.  After these conversions, if the argument
      does not have arithmetic, enumeration, pointer, pointer to member,  or
      class  type, the program is ill-formed.  If the argument has a non-POD
      class type (_class_), the behavior is undefined.  If the argument  has
      integral  or  enumeration  type that is subject to the integral promo-
      tions (_conv.prom_), or a floating point type that is subject  to  the
      floating point promotion (_conv.fpprom_), the value of the argument is
      converted to the promoted type before the call.  These promotions  are
      referred to as the default argument promotions.

    8 The order of evaluation of arguments is unspecified.  All side effects
      of argument expression evaluations take effect before the function  is
      entered.   The  order  of evaluation of the postfix expression and the
      argument expression list is unspecified.

    9 Recursive calls are permitted.

    10A function call is an lvalue if and only if the result type is a  ref-
      erence.

      5.2.3  Explicit type conversion (functional           [expr.type.conv]
           notation)

    1 A  simple-type-specifier  (_dcl.type_)  followed  by  a  parenthesized
      expression-list  constructs  a  value  of the specified type given the
      expression list.  If the expression list is a single  expression,  the
      type  conversion  expression  is  equivalent  (in  definedness, and if
      defined   in   meaning)   to   the   corresponding   cast   expression
      (_expr.cast_).   If  the simple-type-specifier specifies a class type,
      the class type shall be complete.  If the  expression  list  specifies
      more  than  a  single value, the type shall be a class with a suitably
      declared constructor (_dcl.init_, _class.ctor_),  and  the  expression

      T(x1, x2, ...)  is equivalent in effect to the declaration T t(x1, x2,
      ...); for some invented temporary variable t, with  the  result  being
      the value of t as an rvalue.

    2 The expression T(), where T is a simple-type-specifier (_dcl.type.sim-
      ple_) for a non-array complete object type or the (possibly  cv-quali-
      fied)  void type, creates an rvalue of the specified type, whose value
      is determined by default-initialization (_dcl.init_).  [Note: if T  is
      a  non-class  type that is cv-qualified, the cv-qualifiers are ignored
      when determining the type of the resulting rvalue (_basic.lval_).  ]

      5.2.4  Pseudo destructor call                            [expr.pseudo]

    1 The use of a pseudo-destructor-name after a dot .  or arrow ->  opera-
      tor  represents  the  destructor for the non-class type named by type-
      name.  The result shall only be used as the operand for  the  function
      call  operator  (),  and the result of such a call has type void.  The
      only effect is the evaluation of the postfix-expression before the dot
      or arrow.

    2 The  left  hand side of the dot operator shall be of scalar type.  The
      left hand side of the arrow operator shall be  of  pointer  to  scalar
      type.   This  scalar  type is the object type.  The type designated by
      the pseudo-destructor-name shall be the same as the object type.  Fur-
      thermore, the two type-names in a pseudo-destructor-name of the form
              ::opt nested-name-specifieropt type-name :: ~ type-name
      shall designate the same scalar type.

      5.2.5  Class member access                                  [expr.ref]

    1 A  postfix  expression followed by a dot .  or an arrow ->, optionally
      followed by the keyword template (_temp.arg.explicit_), and then  fol-
      lowed  by  an  id-expression,  is  a  postfix expression.  The postfix
      expression before the dot or arrow is evaluated;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).  In these cases, the id-expression shall name a member  of  the
      class  or  of  one  of its base classes.  [Note: because the name of a
      class is inserted in its class scope (_class_), the name of a class is
      also   considered   a   nested   member   of  that  class.   ]  [Note:
      _basic.lookup.classref_ describes how names are looked up after the  .
      and -> operators.  ]

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

    3 If E1 has the type "pointer to class X," then the expression E1->E2 is
      converted to the equivalent form (*(E1)).E2;  the  remainder  of  this
      subclause will address only the first  option  (dot)6).   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_.

    4 If E2 is declared to have type "reference to  T",  then  E1.E2  is  an
      lvalue; the type of E1.E2 is T.  Otherwise, one of the following rules
      applies.

      --If E2 is a static data member, and the type of E2 is T,  then  E1.E2
        is  an  lvalue;  the  expression  designates the named member of the
        class.  The type of E1.E2 is T.

      --If E2 is a non-static data member, and the type of E1  is  "cq1  vq1
        X", and the type of E2 is "cq2 vq2 T", the expression designates the
        named member of the object designated by the first  expression.   If
        E1  is  an  lvalue,  then E1.E2 is an lvalue.  Let the notation vq12
        stand for the "union" of vq1 and vq2 ; that is, if  vq1  or  vq2  is
        volatile,  then  vq12 is volatile.  Similarly, let the notation cq12
        stand for the "union" of cq1 and cq2; that is,  if  cq1  or  cq2  is
        const,  then  cq12 is const.  If E2 is declared to be a mutable mem-
        ber, then the type of E1.E2 is "vq12 T".  If E2 is not  declared  to
        be a mutable member, then the type of E1.E2 is "cq12 vq12 T".

      --If  E2 is a (possibly overloaded) member function, function overload
        resolution (_over.match_) is used to determine whether E1.E2  refers
        to a static or a non-static member function.

        --If  it  refers  to a static member function, and the type of E2 is
          "function of (parameter type list) returning T", then E1.E2 is  an
          lvalue; the expression designates the static member function.  The
          type of E1.E2 is the same type as that of E2, namely "function  of
          (parameter type list) returning T".

        --Otherwise,  if  E1.E2  refers to a non-static member function, and
          the type of E2 is "function of (parameter type list) cv  returning
          T", then E1.E2 is not an lvalue.  The expression designates a non-
          static member function.  The expression can be used  only  as  the
          left-hand  operand  of  a  member  function  call  (_class.mfct_).
          [Note: any redundant set of parentheses surrounding the expression
          is  ignored  (_expr.prim_).   ]  The type of E1.E2 is "function of
          (parameter type list) cv returning T".

      --If E2 is a nested type, the expression E1.E2 is ill-formed.

      _________________________
      6)  Note that if E1 has the type "pointer to class X", then (*(E1)) is
      an lvalue.

      --If E2 is a member enumerator, and the type of E2 is T,  the  expres-
        sion E1.E2 is not an lvalue.  The type of E1.E2 is T.

    5 [Note:  "class  objects"  can  be  structures (_class.mem_) and unions
      (_class.union_).  Classes are discussed in clause _class_.  ]

      5.2.6  Increment and decrement                        [expr.post.incr]

    1 The value obtained by applying a postfix ++  is  the  value  that  the
      operand  had  before applying the operator.  [Note: the value obtained
      is a copy of the original value ] The operand shall  be  a  modifiable
      lvalue.   The  type  of  the  operand shall be an arithmetic type or a
      pointer to a complete object type.  After the  result  is  noted,  the
      value  of  the object is modified by adding 1 to it, unless the object
      is of type bool, in which case it is set to true.  [Note: this use  is
      deprecated, see annex _depr_.  ] The result is an rvalue.  The type of
      the result is the cv-unqualified version of the type of  the  operand.
      See also _expr.add_ and _expr.ass_.

    2 The operand of postfix -- is decremented analogously to the postfix ++
      operator, except that the operand shall not be of type  bool.   [Note:
      For prefix increment and decrement, see _expr.pre.incr_.  ]

      5.2.7  Dynamic cast                                [expr.dynamic.cast]

    1 The  result of the expression dynamic_cast<T>(v) is the result of con-
      verting the expression v to type T.  T shall be a pointer or reference
      to a complete class type, or "pointer to cv void".  Types shall not be
      defined in a dynamic_cast.  The dynamic_cast operator shall  not  cast
      away constness (_expr.const.cast_).

    2 If  T is a pointer type, v shall be an rvalue of a pointer to complete
      class type, and the result is an rvalue of type T.  If T is  a  refer-
      ence  type,  v  shall  be  an lvalue of a complete class type, and the
      result is an lvalue of the type referred to by T.

    3 If the type of v is the same as the required result type  (which,  for
      convenience,  will be called R in this description), or it is the same
      as R except that the class object type in R is more cv-qualified  than
      the  class object type in v, the result is v (converted if necessary).

    4 If the value of v is a null pointer value in  the  pointer  case,  the
      result is the null pointer value of type R.

    5 If T is "pointer to cv1 B" and v has type "pointer to cv2 D" such that
      B is a base class of D, the result is a pointer to the unique  B  sub-
      object of the D object pointed to by v.  Similarly, if T is "reference
      to cv1 B" and v has type cv2 D" such that B is a base class of D,  the
      result  is  an  lvalue  for  the unique7) B sub-object of the D object
      referred to by v.  In both the pointer and reference cases, cv1  shall
      _________________________
      7) The most derived object (_intro.object_) pointed or referred to  by
      v  can contain other B objects as base classes, but these are ignored.

      be  the  same  cv-qualification  as, or greater cv-qualification than,
      cv2, and B shall be an accessible unambiguous base class of D.  [Exam-
      ple:
              struct B {};
              struct D : B {};
              void foo(D* dp)
              {
                  B*  bp = dynamic_cast<B*>(dp);  // equivalent to B* bp = dp;
              }
       --end example]

    6 Otherwise,  v shall be a pointer to or an lvalue of a polymorphic type
      (_class.virtual_).

    7 If T is "pointer to cv void," then the result is a pointer to the most
      derived  object  pointed  to  by  v.   Otherwise,  a run-time check is
      applied to see if the object pointed or referred to by v can  be  con-
      verted to the type pointed or referred to by T.

    8 The run-time check logically executes as follows:

      --If,  in the most derived object pointed (referred) to by v, v points
        (refers) to a public base class sub-object of a  T  object,  and  if
        only  one  object  of  type T is derived from the sub-object pointed
        (referred) to by v, the result is a pointer (an lvalue referring) to
        that T object.

      --Otherwise, if v points (refers) to a public base class sub-object of
        the most derived object, and the type of the most derived object has
        an  unambiguous public base class of type T, the result is a pointer
        (an lvalue referring) to  the  T  sub-object  of  the  most  derived
        object.

      --Otherwise, the run-time check fails.

    9 The  value  of a failed cast to pointer type is the null pointer value
      of the required result type.  A failed cast to reference  type  throws
      bad_cast (_lib.bad.cast_).  [Example:
              class A { virtual void f(); };
              class B { virtual void g(); };
              class D : public virtual A, private B {};
              void g()
              {
                  D   d;
                  B*  bp = (B*)&d;  // cast needed to break protection
                  A*  ap = &d;      // public derivation, no cast needed
                  D&  dr = dynamic_cast<D&>(*bp);  // fails
                  ap = dynamic_cast<A*>(bp);       // fails
                  bp = dynamic_cast<B*>(ap);       // fails
                  ap = dynamic_cast<A*>(&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;                    // succeeds: finds unique A
                  D*  dp  = dynamic_cast<D*>(ap);  // fails: yields 0
                                                   // f has two D sub-objects
                  E*  ep  = (E*)ap;                // ill-formed:
                                                   // cast from virtual base
                  E*  ep1 = dynamic_cast<E*>(ap);  // succeeds
              }
        --end example] [Note: Clause _class.cdtor_ describes the behavior of
      a dynamic_cast applied to an object under construction or destruction.
      ]

      5.2.8  Type identification                               [expr.typeid]

    1 The  result  of  a  typeid  expression  is  an  lvalue  of  type const
      std::type_info (_lib.type.info_).  The lifetime of the object referred
      to  by  the  lvalue extends to the end of the program.  Whether or not
      the destructor is called for the type_info object at the  end  of  the
      program is unspecified.

    2 When  typeid  is applied to an lvalue expression whose type is a poly-
      morphic class type (_class.virtual_), the result refers to a type_info
      object   representing   the   type   of   the   most   derived  object
      (_intro.object_) (that is, the  dynamic  type)  to  which  the  lvalue
      refers.   If the lvalue expression is obtained by applying the unary *
      operator  to  a  pointer8)  and  the  pointer  is a null pointer value
      (_conv.ptr_), the typeid expression throws  the  bad_typeid  exception
      (_lib.bad.typeid_).

    3 When  typeid  is  applied  to  an expression other than an lvalue of a
      polymorphic class type, the result refers to a type_info object repre-
      senting   the   static   type  of  the  expression.   Lvalue-to-rvalue
      (_conv.lval_),  array-to-pointer  (_conv.array_),   and   function-to-
      pointer  (_conv.func_)  conversions are not applied to the expression.
      If the type of the expression is a class type, the class shall be com-
      pletely-defined.  The expression is not evaluated.

    4 When  typeid is applied to a type-id, the result refers to a type_info
      object representing the type of the type-id.  If the type of the type-
      id  is a reference type, the result of the typeid expression refers to
      a type_info object representing the referenced type.  If the  type  of
      the  type-id is a class type or a reference to a class type, the class
      shall be completely-defined.  Types shall not be defined in the  type-
      id.

      _________________________
      8) If p is an expression of pointer type, then *p, (*p), *(p), ((*p)),
      *((p)), and so on all meet this requirement.

    5 The  top-level  cv-qualifiers  of the lvalue expression or the type-id
      that is the operand of typeid are always ignored.  [Example:
              class D { ... };
              D d1;
              const D d2;
              typeid(d1) == typeid(d2);      // yields true
              typeid(D)  == typeid(const D); // yields true
              typeid(D)  == typeid(d2);      // yields true
              typeid(D)  == typeid(const D&);// yields true
       --end example]

    6 If the header <typeinfo> (_lib.type.info_) is not included prior to  a
      use of typeid, the program is ill-formed.

    7 [Note:  clause  _class.cdtor_ describes the behavior of typeid applied
      to an object under construction or destruction.  ]

      5.2.9  Static cast                                  [expr.static.cast]

    1 The result of the expression static_cast<T>(v) is the result  of  con-
      verting  the  expression  v  to type T.  If T is a reference type, the
      result is an lvalue; otherwise, the result is an rvalue.  Types  shall
      not  be  defined in a static_cast.  The static_cast operator shall not
      cast away constness (_expr.const.cast_).

    2 An expression e can be explicitly  converted  to  a  type  T  using  a
      static_cast  of the form static_cast<T>(e) if the declaration T t(e);"
      is well-formed, for some invented temporary variable  t  (_dcl.init_).
      The  effect  of  such an explicit conversion is the same as performing
      the declaration and initialization and then using the temporary  vari-
      able as the result of the conversion.  The result is an lvalue if T is
      a reference type (_dcl.ref_), and an rvalue otherwise.  The expression
      e is used as an lvalue if and only if the initialization uses it as an
      lvalue.

    3 Otherwise, the static_cast shall perform one of the conversions listed
      below.   No  other  conversion  shall  be performed explicitly using a
      static_cast.

    4 Any expression can be explicitly converted  to  type  cv  void."   The
      expression  value  is discarded.  [Note: however, if the value is in a
      temporary variable (_class.temporary_), the destructor for that  vari-
      able  is not executed until the usual time, and the value of the vari-
      able is preserved for the purpose of executing the destructor.  ]  The
      lvalue-to-rvalue  (_conv.lval_),  array-to-pointer (_conv.array_), and
      function-to-pointer (_conv.func_) standard conversions are not applied
      to the expression.

    5 An lvalue of type cv1 B", where B is a class type, can be cast to type
      "reference to cv2 D", where D is  a  class  derived  (_class.derived_)
      from B, if a valid standard conversion from "pointer to D" to "pointer
      to B" exists (_conv.ptr_), cv2 is the  same  cv-qualification  as,  or
      greater  cv-qualification than, cv1, and B is not a virtual base class
      of D.  The result is an lvalue of type cv2 D."  If the lvalue of  type

      cv1  B"  is  actually  a sub-object of an object of type D, the lvalue
      refers to the enclosing object of type D.  Otherwise,  the  result  of
      the cast is undefined.  [Example:
              struct B {};
              struct D : public B {};
              D d;
              B &br = d;

              static_cast<D&>(br);    // produces lvalue to the original d object
       --end example]

    6 The  inverse  of any standard conversion sequence (_conv_), other than
      the lvalue-to-rvalue (_conv.lval_),  array-to-pointer  (_conv.array_),
      function-to-pointer  (_conv.func_),  and boolean (_conv.bool_) conver-
      sions, 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 D" to "pointer to B" exists (_conv.ptr_), cv2 is the same
      cv-qualification as, or greater cv-qualification than, cv1, and  B  is
      not a virtual base class of D.  The null pointer value (_conv.ptr_) is
      converted to the null pointer value of the destination type.   If  the
      rvalue  of  type  "pointer  to cv1 B" points to a B that is actually a
      sub-object of an object of type D, the resulting pointer points to the
      enclosing  object  of  type  D.   Otherwise, the result of the cast is
      undefined.

    9 An rvalue of type "pointer to member of D of type cv1 T" can  be  con-
      verted  to  an  rvalue of type "pointer to member of B of type cv2 T",
      where B is a base class (_class.derived_) of D, if  a  valid  standard
      conversion from "pointer to member of B of type T" to "pointer to mem-
      ber of D of type T" exists (_conv.mem_), and cv2 is the same cv-quali-
      fication as, or greater cv-qualification than, cv1.9) The null  member
      pointer  value  (_conv.mem_)  is  converted to the null member pointer
      value of the destination type.  If class B contains the original  mem-
      ber,  or is a base or derived class of the class containing the origi-
      nal member, the resulting pointer to member  points  to  the  original
      member.   Otherwise,  the  result  of  the  cast is undefined.  [Note:
      although class B need not contain the  original  member,  the  dynamic
      type of the object on which the pointer to member is dereferenced must
      contain the original member; see _expr.mptr.oper_.  ]
      _________________________
      9)  Function types (including those used in pointer to member function
      types) are never cv-qualified; see _dcl.fct_ .

      5.2.10  Reinterpret cast                       [expr.reinterpret.cast]

    1 The result of the expression reinterpret_cast<T>(v) is the  result  of
      converting  the expression v to type T.  If T is a reference type, the
      result is an lvalue; otherwise,  the  result  is  an  rvalue  and  the
      lvalue-to-rvalue  (_conv.lval_),  array-to-pointer (_conv.array_), and
      function-to-pointer (_conv.func_) standard conversions  are  performed
      on  the  the  expression  v.  Types shall not be defined in a reinter-
      pret_cast.  Conversions that can be performed explicitly  using  rein-
      terpret_cast  are  listed below.  No other conversion can be performed
      explicitly using reinterpret_cast.

    2 The reinterpret_cast operator shall not cast away  constness.   [Note:
      see  _expr.const.cast_  for  the  definition  of ``casting away const-
      ness''.  ] Any expression may be cast to its own type using a reinter-
      pret_cast operator.

    3 The  mapping  performed by reinterpret_cast is implementation-defined.
      [Note: it might, or might not, produce a representation different from
      the original value.  ]

    4 A  pointer  can  be  explicitly  converted  to any integral type large
      enough to hold it.  The  mapping  function  is  implementation-defined
      [Note:  it  is  intended  to  be  unsurprising  to  those who know the
      addressing structure of the underlying machine.  ]

    5 A value of integral type or enumeration type can  be  explicitly  con-
      verted to a pointer.10) A pointer converted to an  integer  of  suffi-
      cient  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 A  pointer to a function can be explicitly converted to a pointer to a
      function of a different  type.   The  effect  of  calling  a  function
      through  a pointer to a function type (_dcl.fct_) that is not the same
      as the type used in the  definition  of  the  function  is  undefined.
      Except  that  converting an rvalue of type "pointer to T1" to the type
      "pointer to T2" (where T1 and T2 are function types) and back  to  its
      original  type yields the original pointer value, the result of such a
      pointer conversion is unspecified.  [Note:  see  also  _conv.ptr_  for
      more details of pointer conversions.  ]

    7 A  pointer to an object can be explicitly converted to a pointer to an
      object  of different type.11) 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
      _________________________
      10)  Converting  an  integral  constant expression (_expr.const_) with
      value zero always yields a null pointer (_conv.ptr_),  but  converting
      other expressions that happen to have value zero need not yield a null
      pointer.
      11) The types may have different cv-qualifiers, subject to the overall
      restriction that a reinterpret_cast cannot cast away constness.

      stricter than those of T1) and back to its original  type  yields  the
      original  pointer  value,  the  result of such a pointer conversion is
      unspecified.

    8 The null pointer value (_conv.ptr_) is converted to the  null  pointer
      value of the destination type.

    9 An  rvalue  of type "pointer to member of X of type T1" can be explic-
      itly converted to an rvalue of type "pointer to member of  Y  of  type
      T2" if T1 and T2 are both function types or both object types.12)  The
      null member pointer value (_conv.mem_) is converted to the null member
      pointer value of the destination type.  The result of this  conversion
      is unspecified, except in the following cases:

      --converting  an rvalue of type "pointer to member function" to a dif-
        ferent pointer to member function type and back to its original type
        yields the original pointer to member value.

      --converting  an  rvalue  of type "pointer to data member of X of type
        T1" to the type "pointer to data member of Y of type T2" (where  the
        alignment  requirements  of T2 are no stricter than those of T1) and
        back to its original type yields  the  original  pointer  to  member
        value.

    10Calling  a member function through a pointer to member that represents
      a function type (_dcl.fct_) that differs from the function type speci-
      fied  on the member function definition results in undefined behavior,
      except when calling a virtual function  whose  function  type  differs
      from  the  function type of the pointer to member only as permitted by
      the rules for overriding virtual functions (_class.virtual_).

    11An lvalue expression of type T1 can be cast to the type "reference  to
      T2"  if  an  expression of type "pointer to T1" can be explicitly con-
      verted to the type "pointer to T2" using a reinterpret_cast.  That is,
      a  reference  cast  reinterpret_cast<T&>(x) has the same effect as the
      conversion *reinterpret_cast<T*>(&x) with the built-in & and *  opera-
      tors.   The  result is an lvalue that refers to the same object as the
      source lvalue, but with a different type.  No temporary is created, no
      copy  is made, and constructors (_class.ctor_) or conversion functions
      (_class.conv_) are not called.13)

      5.2.11  Const cast                                   [expr.const.cast]

    1 The result of the expression const_cast<T>(v) is of type T.  If T is a
      reference  type,  the result is an lvalue; otherwise, the result is an
      rvalue  and,  the  lvalue-to-rvalue  (_conv.lval_),   array-to-pointer
      (_conv.array_), and function-to-pointer (_conv.func_) standard conver-
      sions are performed on the expression v.  Types shall not  be  defined
      in  a  const_cast.  Conversions that can be performed explicitly using
      _________________________
      12) T1 and T2 may have different cv-qualifiers, subject to the overall
      restriction that a reinterpret_cast cannot cast away constness.
      13) This is sometimes referred to as a type pun.

      const_cast are listed below.  No other conversion shall  be  performed
      explicitly using const_cast.

    2 Any  expression  may be cast to its own type using a const_cast opera-
      tor.

    3 For two pointer types T1 and T2 where

                T1 is cv1,0 pointer to cv1,1 pointer to ... cv1,n-1 pointer to cv1,n T
      and

                T2 is cv2,0 pointer to cv2,1 pointer to ... cv2,n-1 pointer to cv2,n T
      where T is any object type or the void type and where cv1,k and  cv2,k
      may  be  different  cv-qualifications,  an  rvalue  of  type T1 may be
      explicitly converted to the type T2 using a const_cast.  The result of
      a pointer const_cast refers to the original object.

    4 An  lvalue of type T1 can be explicitly converted to an lvalue of type
      T2 using the cast const_cast<T2&> (where T1 and T2 are  object  types)
      if  a pointer to T1 can be explicitly converted to the type pointer to
      T2 using a const_cast.  The result of a reference const_cast refers to
      the original object.

    5 For  a  const_cast  involving  pointers  to  data members, multi-level
      pointers to data members and multi-level mixed pointers  and  pointers
      to  data  members (_conv.qual_), the rules for const_cast are the same
      as those used for pointers; the "member" aspect of a pointer to member
      is  ignored  when  determining  where  the  cv-qualifiers are added or
      removed by the const_cast.  The result of a  pointer  to  data  member
      const_cast  refers to the same member as the original (uncast) pointer
      to data member.

    6 A null pointer value (_conv.ptr_) is converted  to  the  null  pointer
      value  of  the  destination  type.   The  null  member  pointer  value
      (_conv.mem_) is converted to the null member pointer value of the des-
      tination type.

    7 [Note:  Depending on the type of the object, a write operation through
      the pointer, lvalue  or  pointer  to  data  member  resulting  from  a
      const_cast  that casts away a const-qualifier14) may produce undefined
      behavior (_dcl.type.cv_).  ]

    8 The  following  rules  define the process known as casting away const-
      ness.  In these rules Tn and Xn  represent  types.   For  two  pointer
      types:

                X1 is T1cv1,1 * ... cv1,N *   where T1 is not a pointer type
                X2 is T2cv2,1 * ... cv2,M *   where T2 is not a pointer type
                K is min(N,M)
      casting  from X1 to X2 casts away constness if, for a non-pointer type
      _________________________
      14) const_cast is not limited to conversions that cast away  a  const-
      qualifier.

      T there does not exist an implicit conversion (_conv_) from:

                Tcv1,(N-K+1) * cv1,(N-K+2) * ... cv1,N *
      to

                Tcv2,(M-K+1) * cv2,(M-K+2) * ... cv2,M *

    9 Casting from an lvalue of type T1 to an lvalue of type T2 using a ref-
      erence  cast  casts  away  constness  if a cast from an rvalue of type
      "pointer to T1" to the type "pointer to T2" casts away constness.

    10Casting from an rvalue of type "pointer to data member of  X  of  type
      T1"  to  the  type "pointer to data member of Y of type T2" casts away
      constness if a cast from an rvalue of type "pointer to T1" to the type
      "pointer to T2" casts away constness.

    11For  multi-level pointer to members and multi-level mixed pointers and
      pointer to members (_conv.qual_), the "member" aspect of a pointer  to
      member  level  is ignored when determining if a const cv-qualifier has
      been cast away.

    12[Note: some conversions which involve only changes in cv-qualification
      cannot  be  done  using const_cast.  For instance, conversions between
      pointers to functions are not covered because such conversions lead to
      values  whose  use  causes  undefined behavior.  For the same reasons,
      conversions between pointers to member functions, and  in  particular,
      the  conversion from a pointer to a const member function to a pointer
      to a non-const member function, are not covered.  ]

      5.3  Unary expressions                                    [expr.unary]

    1 Expressions with unary operators group right-to-left.
              unary-expression:
                      postfix-expression
                      ++  cast-expression
                      --  cast-expression
                      unary-operator cast-expression
                      sizeof unary-expression
                      sizeof ( type-id )
                      new-expression
                      delete-expression
              unary-operator: one of
                      *  &  +  -  !  ~

      5.3.1  Unary operators                                 [expr.unary.op]

    1 The unary * operator performs indirection: the expression to which  it
      is  applied  shall  be  a pointer to an object type, or a pointer to a
      function type and the result is an lvalue referring to the  object  or
      function  to  which the expression points.  If the type of the expres-
      sion is "pointer to T," the type of  the  result  is  "T."   [Note:  a
      pointer  to  an  incomplete type (other than cv void ) can be derefer-
      enced.  The lvalue thus obtained can be used in limited ways (to  ini-
      tialize  a  reference, for example); this lvalue must not be converted

      to an rvalue, see _conv.lval_.  ]

    2 The result of the unary & operator is a pointer to its  operand.   The
      operand  shall  be an lvalue or a qualified-id.  In the first case, if
      the type of the expression is "T," the type of the result is  "pointer
      to  T."   In  particular,  the  address of an object of type "cv T" is
      "pointer to cv T," with the same cv-qualifiers.  For  a  qualified-id,
      if  the  member is a static member of type "T", the type of the result
      is plain "pointer to T."  If the member is a nonstatic member of class
      C  of  type T, the type of the result is "pointer to member of class C
      of type T."  [Example:
              struct A { int i; };
              struct B : A { };
              ... &B::i ... // has type "int A::*"
       --end example] [Note: a pointer to member formed from a mutable  non-
      static  data member (_dcl.stc_) does not reflect the mutable specifier
      associated with the nonstatic data member.  ]

    3 A pointer to member is only formed when an explicit & is used and  its
      operand  is  a  qualified-id not enclosed in parentheses.  [Note: that
      is, the expression &(qualified-id), where the qualified-id is enclosed
      in  parentheses,  does not form an expression of type "pointer to mem-
      ber."  Neither does qualified-id, because there is no implicit conver-
      sion  from  a qualified-id for a nonstatic member function to the type
      "pointer to member function" as there is from an  lvalue  of  function
      type to the type "pointer to function" (_conv.func_).  Nor is &unqual-
      ified-id a pointer to member, even within the scope  of  the  unquali-
      fied-id's class.  ]

    4 The  address  of an object of incomplete type can be taken, but if the
      complete type of that object is a class type that declares operator&()
      as  a member function, then the behavior is undefined (and no diagnos-
      tic is required).  The operand of & shall not be a bit-field.

    5 The address of an overloaded function (_over_) can be taken only in  a
      context that uniquely determines which version of the overloaded func-
      tion is referred to (see _over.over_).  [Note: since the context might
      determine  whether  the  operand is a static or nonstatic member func-
      tion, the context can also affect  whether  the  expression  has  type
      "pointer to function" or "pointer to member function."  ]

    6 The  operand  of  the unary + operator shall have arithmetic, enumera-
      tion, or pointer type and the result is the  value  of  the  argument.
      Integral  promotion  is performed on integral or enumeration operands.
      The type of the result is the type of the promoted operand.

    7 The operand of the unary - operator shall have arithmetic or  enumera-
      tion  type  and  the  result is the negation of its operand.  Integral
      promotion is performed on integral or enumeration operands.  The nega-
      tive of an unsigned quantity is computed by subtracting its value from
      2n, where n is the number of bits in the promoted operand.   The  type
      of the result is the type of the promoted operand.

    8 The  operand  of  the  logical negation operator !  is implicitly con-
      verted to bool (_conv_); its value is true if the converted operand is
      false and false otherwise.  The type of the result is bool.

    9 The  operand  of ~ shall have integral or enumeration type; the result
      is the one's complement of its operand.  Integral promotions are  per-
      formed.   The  type of the result is the type of the promoted operand.
      There is an ambiguity in the  unary-expression  ~X(),  where  X  is  a
      class-name.   The  ambiguity  is  resolved in favor of treating ~ as a
      unary complement rather than treating ~T as referring to a destructor.

      5.3.2  Increment and decrement                         [expr.pre.incr]

    1 The operand of prefix ++ is modified by adding 1, or set to true if it
      is bool (this use is deprecated).  The operand shall be  a  modifiable
      lvalue.   The  type  of  the  operand shall be an arithmetic type or a
      pointer to a completely-defined object type.  The  value  is  the  new
      value  of the operand; it is an lvalue.  If x is not of type bool, the
      expression ++x is equivalent to x+=1.  [Note: see the  discussions  of
      addition (_expr.add_) and assignment operators (_expr.ass_) for infor-
      mation on conversions.  ]

    2 The operand of prefix -- is modified by substracting 1.   The  operand
      shall  not be of type bool.  The requirements on the operand of prefix
      -- and the properties of its result are otherwise the same as those of
      prefix   ++.    [Note:   For  postfix  increment  and  decrement,  see
      _expr.post.incr_.  ]

      5.3.3  Sizeof                                            [expr.sizeof]

    1 The sizeof operator yields the number of bytes in the object represen-
      tation  of its operand.  The operand is either an expression, which is
      not evaluated, or a parenthesized type-id.  The sizeof operator  shall
      not  be applied to an expression that has function or incomplete type,
      or to an  enumeration  type  before  all  its  enumerators  have  been
      declared,  or to the parenthesized name of such types, or to an lvalue
      that designates a bit-field.  sizeof(char),  sizeof(signed  char)  and
      sizeof(unsigned char) are 1; the result of sizeof applied to any other
      fundamental  type  (_basic.fundamental_)  is   implementation-defined.
      [Note:   in   particular,   sizeof(bool)   and   sizeof(wchar_t)   are
      implementation-defined.15) ] [Note: See _intro.memory_ for the defini-
      tion  of byte and _basic.types_ for the definition of object represen-
      tation.  ]

    2 When applied to a reference or a reference type,  the  result  is  the
      size  of  the referenced type.  When applied to a class, the result is
      the number of bytes in an object of that class including  any  padding
      required  for placing objects of that type in an array.  The size of a
      most derived class shall be greater than zero  (_intro.object_).   The
      result of applying sizeof to a base class subobject is the size of the
      base class type.16) When applied to an array, the result is the  total
      _________________________
      15) sizeof(bool) is not required to be 1.
      16) The actual size of a base class subobject may be less than the re-

      number  of bytes in the array.  This implies that the size of an array
      of n elements is n times the size of an element.

    3 The sizeof operator can be applied to a pointer  to  a  function,  but
      shall not be applied directly to a function.

    4 The  lvalue-to-rvalue  (_conv.lval_), array-to-pointer (_conv.array_),
      and function-to-pointer (_conv.func_)  standard  conversions  are  not
      applied to the operand of sizeof.

    5 Types shall not be defined in a sizeof expression.

    6 The  result  is  a constant of 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
      object  type,  but  not  an  abstract  class  type  or  array  thereof
      (_intro.object_,  _basic.types_,  _class.abstract_).   [Note:  because
      references  are  not  objects,  references  cannot  be created by new-
      expressions.  ] [Note: the type-id may  be  a  cv-qualified  type,  in
      which case the object created by the new-expression has a cv-qualified
      type.  ]
              new-expression:
                      ::opt new new-placementopt new-type-id new-initializeropt
                      ::opt new new-placementopt ( type-id ) new-initializeropt
              new-placement:
                      ( expression-list )
              new-type-id:
                      type-specifier-seq new-declaratoropt
              new-declarator:
                      ptr-operator new-declaratoropt
                      direct-new-declarator
              direct-new-declarator:
                      [ expression ]
                      direct-new-declarator [ constant-expression ]
              new-initializer:
                      ( expression-listopt )
      Entities created by a new-expression  have  dynamic  storage  duration
      (_basic.stc.dynamic_).   [Note:  the lifetime of such an entity is not
      necessarily restricted to the scope in which it is created.  ] If  the
      entity  is a non-array object, the new-expression returns a pointer to
      the object created.  If it is an array, the new-expression  returns  a
      pointer to the initial element of the array.

    2 The  new-type-id  in a new-expression is the longest possible sequence
      of  new-declarators.   [Note:  this   prevents   ambiguities   between
      _________________________
      sult  of applying sizeof to the subobject, due to virtual base classes
      and less strict padding requirements on base class subobjects.

      declarator  operators  &, *, [], 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 the new-type-id of a new-expression.

    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] have
      type 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_)  and evaluate to a strictly
      positive value.  The expression in a direct-new-declarator shall  have
      integral type (_basic.fundamental_) with a non-negative value.  [Exam-
      ple: if n is a variable of type int,  then  new float[n][5]  is  well-
      formed  (because  n is the expression of a direct-new-declarator), but
      new float[5][n] is ill-formed (because n  is  not  a  constant-expres-
      sion).   If n is negative, the effect of new float[n][5] is undefined.
      ]

    8 When the value of the expression in a direct-new-declarator  is  zero,
      the  allocation  function  is called to allocate an array with no ele-
      ments.  The pointer returned by the  new-expression  is  non-null  and
      distinct from the pointer to any other object.

    9 Storage  for  the  object created by a new-expression is obtained from
      the appropriate allocation function  (_basic.stc.dynamic.allocation_).
      When  the  allocation  function is called, the first argument shall be
      the amount of space requested (which shall be no less than the size of
      the object being created and which may be greater than the size of the
      object being created only if the object is an array).

    10An implementation shall provide default  definitions  for  the  global
      allocation    functions    operator new()    for    non-array    types
      (_basic.stc.dynamic_,  _lib.new.delete.single_)  and  operator new[]()
      for  array  types  (_lib.new.delete.array_).  [Note: A C++ program can

      provide alternative  definitions  of  these  functions  (_lib.replace-
      ment.functions_),  and/or  class-specific  versions (_class.free_).  ]
      When the keyword new in a new-expression is preceded by the  unary  ::
      operator, the global allocation function is used to allocate the stor-
      age.

    11The new-placement syntax is used to supply additional arguments to  an
      allocation  function.   If used, overload resolution is performed on a
      function call created by assembling an argument list consisting of the
      amount  of space requested (the first argument) and the expressions in
      the new-placement part of the new-expression (the second and  succeed-
      ing  arguments).  The first of these arguments has type size_t and the
      remaining arguments have the corresponding types of the expressions in
      the new-placement.

    12[Example:

      --new T results in a call of operator new(sizeof(T)),

      --new(2,f) T results in a call of operator new(sizeof(T),2,f),

      --new T[5] results in a call of operator new[](sizeof(T)*5+x), and

      --new(2,f) T[5]        results        in        a        call       of
        operator new[](sizeof(T)*5+y,2,f).

      Here, x and y are non-negative, implementation-defined  values  repre-
      senting  array  allocation  overhead.  Their value might vary from one
      invocation of new to another.  ]

    13The allocation function shall either return null or  a  pointer  to  a
      block  of  storage  in  which  space  for  the  object shall have been
      reserved.  [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.  ]

    14A  new-expression  that  creates  an object of type T initializes that
      object as follows:

      --If the new-initializer is omitted:

        --If T is a (possibly cv-qualified) non-POD  class  type  (or  array
          thereof), the object is default-initialized (_dcl.init_).  If T is
          a const-qualified type, the underlying class  type  shall  have  a
          user-declared default constructor.

        --Otherwise,  the object created has indeterminate value.  If T is a
          const-qualified type, or a (possibly cv-qualified) POD class  type
          (or array thereof) containing (directly or indirectly) a member of
          const-qualified type, the program is ill-formed;

      --If the new-initializer is of  the  form  (),  default-initialization

        shall be performed (_dcl.init_);

      --If  the  new-initializer  is of the form expression-list) and T is a
        class type, the appropriate constructor is called, using expression-
        list as the arguments (_dcl.init_);

      --If  the  new-initializer is of the form expression-list) and T is an
        arithmetic, enumeration,  pointer,  or  pointer-to-member  type  and
        expression-list comprises exactly one expression, then the object is
        initialized to the (possibly  converted)  value  of  the  expression
        (_dcl.init_);

      --Otherwise the new-expression is ill-formed.

    15If  the  new-expression  creates  an  object or an array of objects of
      class type, access and ambiguity control are done for  the  allocation
      function,  the deallocation function (_class.free_), and the construc-
      tor (_class.ctor_).  If the new expression creates an array of objects
      of  class type, access and ambiguity control are done for the destruc-
      tor (_class.dtor_).

    16The allocation function can indicate failure by throwing  a  bad_alloc
      exception (_except_, _lib.bad.alloc_).  In this case no initialization
      is done.

    17If any part of the object initialization described above17) terminates
      by throwing an exception and the new-expression  does  not  contain  a
      new-placement,        then       the       deallocation       function
      (_basic.stc.dynamic.deallocation_, _class.free_) is called to free the
      memory  in  which  the  object  was being constructed, after which the
      exception continues to propagate in the context of the new-expression.

    18If any part of the object initialization described above terminates by
      throwing an exception and the new-expression contains a new-placement,
      if the type of the object being created is a class type, a name lookup
      is performed on the name of operator  delete  using  the  same  lookup
      rules as those used to find operator new (_class.free_).  Otherwise, a
      name lookup is performed on the name of operator delete in  the  scope
      of  the new-expression (or in global scope for ::new ).  If the lookup
      succeeds and exactly one of the declarations found matches the  decla-
      ration  of  that  placement  operator new, then the matching placement
      operator delete shall  be  called  (_basic.stc.dynamic.deallocation_).
      If  no  matching  placement delete is found, propagating the exception
      does not cause the object to be deleted.  [Note: this  is  appropriate
      when  the  called operator new does not allocate memory; otherwise, it
      is likely to result in a memory leak.  ]

    19A declaration of placement operator delete matches the declaration  of
      a  placement  operator  new  when it has the same number of parameters
      and, after parameter transformations (_dcl.fct_), all parameter  types
      _________________________
      17) This may include evaluating a  new-initializer  and/or  calling  a
      constructor.

      except the first are identical.

    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.

    22Whether  the  allocation function is called before evaluating the con-
      structor arguments or after evaluating the constructor  arguments  but
      before  entering  the constructor is unspecified.  It is also unspeci-
      fied whether the arguments to a constructor are evaluated if the allo-
      cation  function returns the null pointer or exits using an exception.

      5.3.5  Delete                                            [expr.delete]

    1 The  delete-expression  operator  destroys  a  most   derived   object
      (_intro.object_) or array created by a new-expression.
              delete-expression:
                      ::opt delete cast-expression
                      ::opt delete [ ] cast-expression
      The  first alternative is for non-array objects, and the second is for
      arrays.  The operand shall have a pointer type, or a class type having
      a  single  conversion  function  (_class.conv.fct_) to a pointer type.
      The result has type void.

    2 If the operand has a class type, the operand is converted to a pointer
      type  by calling the above-mentioned conversion function, and the con-
      verted operand is used in  place  of  the  original  operand  for  the
      remainder of this section.  In either alternative, if the value of the
      operand of delete is the null pointer the operation has no effect.  In
      the  first  alternative  (delete  object), the value of the operand of
      delete shall be a pointer to a non-array  object  created  by  a  new-
      expression, or a pointer to a sub-object (_intro.object_) representing
      a base class of such an object (_class.derived_).  If not, the  behav-
      ior is undefined.  In the second alternative (delete array), the value
      of the operand of delete shall be the  pointer  value  which  resulted
      from a previous array new-expression.18) If not, the behavior is unde-
      fined.  [Note: this means that the  syntax  of  the  delete-expression
      must  match the type of the object allocated by new, not the syntax of
      the new-expression.  ] [Note: a pointer to a const  type  can  be  the
      operand  of  a delete-expression; it is not necessary to cast away the
      constness (_expr.const.cast_) of the pointer expression before  it  is
      _________________________
      18)  For  non-zero-length arrays, this is the same as a pointer to the
      first element of the array  created  by  that  new-expression.   Zero-
      length arrays do not have a first element.

      used as the operand of the delete-expression.  ]

    3 In  the  first  alternative (delete object), if the static type of the
      operand is different from its dynamic type, the static type shall be a
      base  class  of  the  operand's dynamic type and the static type shall
      have a virtual destructor or the behavior is undefined.  In the second
      alternative  (delete  array)  if  the dynamic type of the object to be
      deleted differs from its static type, the behavior is undefined.19)

    4 The  cast-expression in a delete-expression shall be evaluated exactly
      once.  If the delete-expression calls the implementation  deallocation
      function (_basic.stc.dynamic.deallocation_), and if the operand of the
      delete expression is not the null pointer constant,  the  deallocation
      function  will  deallocate  the storage referenced by the pointer thus
      rendering the pointer invalid.  [Note: the value  of  a  pointer  that
      refers to deallocated storage is indeterminate.  ]

    5 If  the object being deleted has incomplete class type at the point of
      deletion and the complete class has  a  non-trivial  destructor  or  a
      deallocation function, the behavior is undefined.

    6 The  delete-expression  will  invoke  the  destructor (if any) for the
      object or the elements of the array being deleted.  In the case of  an
      array,  the  elements will be destroyed in order of decreasing address
      (that is, in reverse order of the completion of their constructor; see
      _class.base.init_).

    7 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.sin-
      gle_) and operator delete[]() for arrays (_lib.new.delete.array_).   A
      C++  program  can  provide  alternative definitions of these functions
      (_lib.replacement.functions_),    and/or    class-specific    versions
      (_class.free_).   When  the  keyword  delete in a delete-expression is
      preceded by the unary :: operator, the global deallocation function is
      used to deallocate the storage.

    9 Access  and ambiguity control are done for both the deallocation func-
      tion and the destructor (_class.dtor_, _class.free_).

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

    1 The result of the expression (T) cast-expression is of  type  T.   The
      result  is an lvalue if T is a reference type, otherwise the result is
      an rvalue.  [Note: if T is a non-class type that is cv-qualified,  the
      cv-qualifiers  are  ignored when determining the type of the resulting
      rvalue; see _basic.lval_.  ]

      _________________________
      19) This implies that an object cannot be deleted using a  pointer  of
      type void* because there are no objects of type void.

    2 An explicit type conversion can be expressed using functional notation
      (_expr.type.conv_),  a   type   conversion   operator   (dynamic_cast,
      static_cast, reinterpret_cast, const_cast), or the cast notation.
              cast-expression:
                      unary-expression
                      ( type-id ) cast-expression

    3 Types shall not be defined in casts.

    4 Any  type conversion not mentioned below and not explicitly defined by
      the user (_class.conv_) is ill-formed.

    5 The conversions performed by

      --a const_cast (_expr.const.cast_),

      --a static_cast (_expr.static.cast_),

      --a static_cast followed by a const_cast,

      --a reinterpret_cast (_expr.reinterpret.cast_), or

      --a reinterpret_cast followed by a const_cast,

      can be performed using the cast notation of explicit type  conversion.
      The  same  semantic restrictions and behaviors apply.  If a conversion
      can be interpreted in more than one of  the  ways  listed  above,  the
      interpretation  that appears first in the list is used, even if a cast
      resulting from that interpretation is ill-formed.  If a conversion can
      be  interpreted  in  more  than one way as a static_cast followed by a
      const_cast, the conversion is ill-formed.  [Example:
              struct A {};
              struct I1 : A {};
              struct I2 : A {};
              struct D : I1, I2 {};
              A *foo( D *p ) {
                      return (A*)( p ); // ill-formed static_cast interpretation
              }
       --end example]

    6 The operand of a cast using the cast notation can be an rvalue of type
      "pointer  to  incomplete  class type".  The destination type of a cast
      using the cast notation can be "pointer to incomplete class type".  In
      such  cases,  even  if there is a inheritance relationship between the
      source and destination classes, whether the  static_cast  or  reinter-
      pret_cast interpretation is used is unspecified.

    7 In  addition to those conversions, the following static_cast and rein-
      terpret_cast operations (optionally followed by  a  const_cast  opera-
      tion)  may  be performed using the cast notation of explicit type con-
      version, even if the base class type is not accessible:

      --a pointer to an object of derived class type or an lvalue of derived
        class  type may be explicitly converted to a pointer or reference to

        an unambiguous base class type, respectively;

      --a pointer to member of derived class type  may  be  explicitly  con-
        verted  to  a  pointer  to member of an unambiguous non-virtual base
        class type;

      --a pointer to an object of non-virtual base class type, an lvalue  of
        non-virtual  base  class type, or a pointer to member of non-virtual
        base class type may be explicitly converted to a pointer,  a  refer-
        ence,  or a pointer to member of a derived class type, respectively.

      5.5  Pointer-to-member operators                      [expr.mptr.oper]

    1 The pointer-to-member operators ->* and .*  group left-to-right.
              pm-expression:
                      cast-expression
                      pm-expression .* cast-expression
                      pm-expression ->* cast-expression

    2 The binary operator .*  binds its second operand, which  shall  be  of
      type  "pointer  to member of T" (where T is a completely-defined class
      type) to its first operand, which shall be of class T or of a class of
      which T is an unambiguous and accessible base class.  The result is an
      object or a function of the type specified by the second operand.

    3 The binary operator ->* binds its second operand, which  shall  be  of
      type  "pointer  to member of T" (where T is a completely-defined class
      type) to its first operand, which shall be of type "pointer to  T"  or
      "pointer  to  a class of which T is an unambiguous and accessible base
      class."  The result is an object or a function of the  type  specified
      by the second operand.

    4 If the dynamic type of the object does not contain the member to which
      the pointer refers, the behavior is undefined.

    5 The restrictions on cv-qualification, and the manner in which the  cv-
      qualifiers  of  the operands are combined to produce the cv-qualifiers
      of the  result,  are  the  same  as  the  rules  for  E1.E2  given  in
      _expr.ref_.  [Note: it is not possible to use a pointer to member that
      refers to a mutable member to modify a const class object.  For  exam-
      ple,
              struct S {
                      mutable int i;
              };
              const S cs;
              int S::* pm = &S::i; // pm refers to mutable member S::i
              cs.*pm = 88;         // ill-formed: cs is a const class
      ]

    6 If  the  result  of  .*  or ->* is a function, then that result can be
      used only as the operand for the function call operator ().  [Example:
              (ptr_to_obj->*ptr_to_mfct)(10);
      calls  the  member  function  denoted  by  ptr_to_mfct  for the object
      pointed to by ptr_to_obj.  ] The result of  a  .*   expression  is  an

      lvalue  only  if its first operand is an lvalue and its second operand
      is a pointer to data member.  The result of an ->*  expression  is  an
      lvalue only if its second operand is a pointer to data member.  If the
      second operand is the null pointer to member value  (_conv.mem_),  the
      behavior is undefined.

      5.6  Multiplicative operators                               [expr.mul]

    1 The multiplicative operators *, /, and % group left-to-right.
              multiplicative-expression:
                      pm-expression
                      multiplicative-expression * pm-expression
                      multiplicative-expression / pm-expression
                      multiplicative-expression % pm-expression

    2 The operands of * and / shall have arithmetic or enumeration type; the
      operands of % shall have integral  or  enumeration  type.   The  usual
      arithmetic conversions are performed on the operands and determine the
      type of the result.

    3 The binary * operator indicates multiplication.

    4 The binary / operator yields the quotient, and the binary  %  operator
      yields  the remainder from the division of the first expression by the
      second.  If the second operand of / or % is zero the behavior is unde-
      fined;  otherwise  (a/b)*b  + a%b is equal to a.  If both operands are
      nonnegative then the remainder is nonnegative; if not, the sign of the
      remainder is implementation-defined20).

      5.7  Additive operators                                     [expr.add]

    1 The additive operators + and - group left-to-right.  The usual  arith-
      metic conversions are performed for operands of arithmetic or enumera-
      tion type.
              additive-expression:
                      multiplicative-expression
                      additive-expression + multiplicative-expression
                      additive-expression - multiplicative-expression
      For addition, either both operands shall have arithmetic  or  enumera-
      tion  type,  or one operand shall be a pointer to a completely defined
      object type and the other shall have integral or enumeration type.

    2 For subtraction, one of the following shall hold:

      --both operands have arithmetic or enumeration type; or

      --both operands are pointers to cv-qualified  or  cv-unqualified  ver-
        sions of the same completely defined object type; or
      _________________________
      20)  According to work underway toward the revision of ISO C, the pre-
      ferred algorithm for integer division follows the rules defined in the
      ISO  Fortran standard, ISO/IEC 1539:1991, in which the quotient is al-
      ways rounded toward zero.

      --the  left  operand  is a pointer to a completely defined object type
        and the right operand has integral or enumeration type.

    3 The result of the binary + operator is the sum of the  operands.   The
      result  of  the binary - operator is the difference resulting from the
      subtraction of the second operand from the first.

    4 For the purposes of these operators, a pointer to  a  nonarray  object
      behaves  the  same  as  a  pointer to the first element of an array of
      length one with the type of the object as its element type.

    5 When an expression that has integral type is added  to  or  subtracted
      from  a  pointer,  the result has the type of the pointer operand.  If
      the pointer operand points to an element of an array object,  and  the
      array is large enough, the result points to an element offset from the
      original element such that the difference of  the  subscripts  of  the
      resulting  and original array elements equals the integral expression.
      In other words, if the expression P points to the i-th element  of  an
      array  object,  the  expressions (P)+N (equivalently, N+(P)) and (P)-N
      (where N has the value n) point to, respectively, the i+n-th and  i-n-
      th  elements  of  the array object, provided they exist.  Moreover, if
      the expression P points to the last element of an  array  object,  the
      expression (P)+1 points one past the last element of the array object,
      and if the expression Q points one past the last element of  an  array
      object,  the  expression (Q)-1 points to the last element of the array
      object.  If both the pointer operand and the result point to  elements
      of  the  same  array object, or one past the last element of the array
      object, the evaluation shall not produce an overflow;  otherwise,  the
      behavior is undefined.

    6 When two pointers to elements of the same array object are subtracted,
      the result is the difference of the subscripts of the two  array  ele-
      ments.   The  type  of  the result is an implementation-defined signed
      integral type; this type shall be the same type  that  is  defined  as
      ptrdiff_t  in the <cstddef> header (_lib.support.types_).  As with any
      other arithmetic overflow, if the result does not  fit  in  the  space
      provided,  the  behavior is undefined.  In other words, if the expres-
      sions P and Q point to, respectively, the i-th and j-th elements of an
      array  object,  the  expression (P)-(Q) has the value i-j provided the
      value fits in an object of type ptrdiff_t.  Moreover, if  the  expres-
      sion  P points either to an element of an array object or one past the
      last element of an array object, and the expression Q  points  to  the
      last  element of the same array object, the expression ((Q)+1)-(P) has
      the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value
      zero if the expression P points one past the last element of the array
      object, even though the expression (Q)+1 does not point to an  element
      of  the  array  object.  Unless both pointers point to elements of the
      same array object, or one past the last element of the  array  object,
      the behavior is undefined.21)
      _________________________
      21) Another way to approach pointer arithmetic is first to convert the
      pointer(s) to character pointer(s): In this scheme the integral  value
      of the expression added to or subtracted from the converted pointer is
      first multiplied by the size of the object originally pointed to,  and

    8 If  the  value  0  is added to or subtracted from a pointer value, the
      result compares equal to the original pointer value.  If two  pointers
      point to the same object or function or both point one past the end of
      the same array or both are null, and the two pointers are  subtracted,
      the  result  compares  equal  to  the  value  0  converted to the type
      ptrdiff_t.

      5.8  Shift operators                                      [expr.shift]

    1 The shift operators << and >> group left-to-right.
              shift-expression:
                      additive-expression
                      shift-expression << additive-expression
                      shift-expression >> additive-expression
      The operands shall be of integral or  enumeration  type  and  integral
      promotions  are performed.  The type of the result is that of the pro-
      moted left operand.  The behavior is undefined if the right operand is
      negative,  or  greater than or equal to the length in bits of the pro-
      moted left operand.

    2 The value of E1 << E2 is E1  (interpreted  as  a  bit  pattern)  left-
      shifted  E2 bit positions; vacated bits are zero-filled.  If E1 has an
      unsigned type, the value of the result is E1 multiplied by  the  quan-
      tity  2  raised  to the power E2, reduced modulo ULONG_MAX+1 if E1 has
      type  unsigned  long,  UINT_MAX+1  otherwise.   [Note:  the  constants
      ULONG_MAX and UINT_MAX are defined in the header <climits>).  ]

    3 The value of E1 >> E2 is E1 right-shifted E2 bit positions.  If E1 has
      an unsigned type or if E1 has a signed type and a  nonnegative  value,
      the  value  of  the  result is the integral part of the quotient of E1
      divided by the quantity 2 raised to the power E2.  If E1 has a  signed
      type  and  a  negative  value,  the resulting value is implementation-
      defined.

      5.9  Relational operators                                   [expr.rel]

    1 The relational operators group left-to-right.  [Example:  a<b<c  means
      (a<b)<c and not (a<b)&&(b<c).  ]

      _________________________
      the  resulting  pointer  is  converted back to the original type.  For
      pointer subtraction, the result of the difference between the  charac-
      ter pointers is similarly divided by the size of the object originally
      pointed to.

    7 When viewed in this way, an implementation need only provide one extra
      byte  (which  might  overlap another object in the program) just after
      the end of the object in order to satisfy the "one past the last  ele-
      ment" requirements.

              relational-expression:
                      shift-expression
                      relational-expression < shift-expression
                      relational-expression > shift-expression
                      relational-expression <= shift-expression
                      relational-expression >= shift-expression
      The  operands shall have arithmetic, enumeration or pointer type.  The
      operators < (less than), > (greater than), <= (less than or equal to),
      and  >=  (greater than or equal to) all yield false or true.  The type
      of the result is bool.

    2 The usual arithmetic conversions are performed on operands  of  arith-
      metic or enumeration type.  Pointer conversions (_conv.ptr_) and qual-
      ification conversions (_conv.qual_) are performed on pointer  operands
      (or on a pointer operand and a null pointer constant) to bring them to
      their composite pointer type.  If one operand is a null  pointer  con-
      stant,  the  composite  pointer type is the type of the other operand.
      Otherwise, if one of the operands has type "pointer to cv1 void", then
      the  other  has type "pointer to cv2 T" and the composite pointer type
      is "pointer to cv12 void", where cv12 is the union  of  cv1  and  cv2.
      Otherwise,  the  composite  pointer  type  is  a  pointer type similar
      (_conv.qual_) to the type of one of the operands, with a cv-qualifica-
      tion signature (_conv.qual_) that is the union of the cv-qualification
      signatures of the operand types.  [Note: this implies that any pointer
      can be compared to a null pointer constant and that any object pointer
      can be compared to a  pointer  to  (possibly  cv-qualified)  void.   ]
      Pointers  to objects or functions of the same type (after pointer con-
      versions) can be compared, with a result defined as follows:

      --If two pointers p and q of the same type point to the same object or
        function,  or  both point one past the end of the same array, or are
        both null, then p<=q and p>=q both yield true and p<q and  p>q  both
        yield false.

      --If  two pointers p and q of the same type point to different objects
        that are not members of the same object  or  elements  of  the  same
        array or to different functions, or if only one of them is null, the
        results of p<q, p>q, p<=q, and p>=q are unspecified.

      --If two pointers point to nonstatic data members of the same  object,
        the  pointer  to the later declared member compares greater provided
        the two members are  not  separated  by  an  access-specifier  label
        (_class.access.spec_) and provided their class is not a union.

      --If  two  pointers point to nonstatic data members of the same object
        separated by an  access-specifier  label  (_class.access.spec_)  the
        result is unspecified.

      --If two pointers point to data members of the same union object, they
        compare equal (after conversion to void*,  if  necessary).   If  two
        pointers  point  to elements of the same array or one beyond the end
        of the array, the pointer to the object with  the  higher  subscript
        compares higher.

      --Other pointer comparisons are unspecified.

      5.10  Equality operators                                     [expr.eq]

    1         equality-expression:
                      relational-expression
                      equality-expression == relational-expression
                      equality-expression != relational-expression
      The  ==  (equal  to) and the != (not equal to) operators have the same
      semantic restrictions, conversions, and result type as the  relational
      operators  except  for  their lower precedence and truth-value result.
      [Note: a<b == c<d is true whenever a<b and c<d have  the  same  truth-
      value.  ]

    2 In addition, pointers to members can be compared, or a pointer to mem-
      ber and a  null  pointer  constant.   Pointer  to  member  conversions
      (_conv.mem_) and qualification conversions (_conv.qual_) are performed
      to bring them to a common type. If one operand is a null pointer  con-
      stant,  the  common  type is the type of the other operand. Otherwise,
      the common type is a pointer to member type similar  (_conv.qual_)  to
      the  type  of  one  of the operands, with a cv-qualification signature
      (_conv.qual_) that is the union of the cv-qualification signatures  of
      the operand types.  [Note: this implies that any pointer to member can
      be compared to a null pointer constant.  ] If both operands are  null,
      they  compare  equal.   Otherwise  if  only  one is null, they compare
      unequal.  Otherwise if either is a pointer to a virtual  member  func-
      tion,  the result is unspecified.  Otherwise they compare equal if and
      only if they would refer to the same member of the same  most  derived
      object  (_intro.object_)  or  the same subobject if they were derefer-
      enced with a hypothetical object of the associated class type.  [Exam-
      ple:
              struct B {
                      int f();
              };
              struct L : B { };
              struct R : B { };
              struct D : L, R { };
              int (B::*pb)() = &B::f;
              int (L::*pl)() = pb;
              int (R::*pr)() = pb;
              int (D::*pdl)() = pl;
              int (D::*pdr)() = pr;
              bool x = (pdl == pdr);    // false
       --end example]

      5.11  Bitwise AND operator                              [expr.bit.and]

    1         and-expression:
                      equality-expression
                      and-expression & equality-expression
      The usual arithmetic conversions are performed; the result is the bit-
      wise function of the operands.  The operator applies only to  integral
      or enumeration operands.

      5.12  Bitwise exclusive OR operator                         [expr.xor]

    1         exclusive-or-expression:
                      and-expression
                      exclusive-or-expression ^ and-expression
      The usual arithmetic conversions are performed; the result is the bit-
      wise exclusive function of the operands.  The operator applies only to
      integral or enumeration operands.

      5.13  Bitwise inclusive OR operator                          [expr.or]

    1         inclusive-or-expression:
                      exclusive-or-expression
                      inclusive-or-expression | exclusive-or-expression
      The usual arithmetic conversions are performed; the result is the bit-
      wise inclusive function of its operands.  The operator applies only to
      integral or enumeration operands.

      5.14  Logical AND operator                              [expr.log.and]

    1         logical-and-expression:
                      inclusive-or-expression
                      logical-and-expression && inclusive-or-expression
      The  &&  operator groups left-to-right.  The operands are both implic-
      itly converted to type bool (_conv_).  The  result  is  true  if  both
      operands  are true and false otherwise.  Unlike &, && guarantees left-
      to-right evaluation: the second operand is not evaluated if the  first
      operand is false.

    2 The result is a bool.  All side effects of the first expression except
      for destruction of temporaries (_class.temporary_) happen  before  the
      second expression is evaluated.

      5.15  Logical OR operator                                [expr.log.or]

    1         logical-or-expression:
                      logical-and-expression
                      logical-or-expression || logical-and-expression
      The  ||  operator groups left-to-right.  The operands are both implic-
      itly converted to bool (_conv_).  It returns true  if  either  of  its
      operands  is true, and false otherwise.  Unlike |, || guarantees left-
      to-right evaluation; moreover, the second operand is not evaluated  if
      the first operand evaluates to true.

    2 The result is a bool.  All side effects of the first expression except
      for destruction of temporaries (_class.temporary_) happen  before  the
      second expression is evaluated.

      5.16  Conditional operator                                 [expr.cond]

    1         conditional-expression:
                      logical-or-expression
                      logical-or-expression ? expression : assignment-expression
      Conditional  expressions group right-to-left.  The first expression is

      implicitly converted to bool (_conv_).  It is evaluated and if  it  is
      true,  the  result  of  the conditional expression is the value of the
      second expression, otherwise that of the third expression.   All  side
      effects  of the first expression except for destruction of temporaries
      (_class.temporary_) happen before the second or  third  expression  is
      evaluated.  Only one of the second and third expressions is evaluated.

    2 If either the second or the third operand has type (possibly cv-quali-
      fied)  void, then the lvalue-to-rvalue (_conv.lval_), array-to-pointer
      (_conv.array_), and function-to-pointer (_conv.func_) standard conver-
      sions  are  performed on the second and third operands, and one of the
      following shall hold:

      --The second or the third operand (but not both) is a throw-expression
        (_except.throw_);  the  result is of the type of the other and is an
        rvalue.

      --Both the second and the third operands have type void; the result is
        of  type void and is an rvalue.  [Note: this includes the case where
        both operands are throw-expressions.  ]

    3 Otherwise, if either the second or the third operand has (possibly cv-
      qualified)  class  or enumeration type, overload resolution is used to
      determine the conversions (if any)  to  be  applied  to  the  operands
      (_over.match.oper_,  _over.built_).   The  conversions thus determined
      are applied, and the converted operands are used in place of the orig-
      inal operands for the remainder of this section.

    4 If  the  second and third operands are lvalues and have the same type,
      the result is of that type and is an lvalue.

    5 Otherwise, the result is an rvalue.   Lvalue-to-rvalue  (_conv.lval_),
      array-to-pointer (_conv.array_), and function-to-pointer (_conv.func_)
      standard conversions are performed on the second and  third  operands.
      After those conversions, one of the following shall hold:

      --The  second  and third operands have the same type; the result is of
        that type.

      --The second and third operands have arithmetic or  enumeration  type;
        the  usual  arithmetic  conversions are performed to bring them to a
        common type, and the result is of that type.

      --The second and third operands have pointer type, or one has  pointer
        type  and  the other is a null pointer constant; pointer conversions
        (_conv.ptr_) and qualification conversions  (_conv.qual_)  are  per-
        formed  to  bring them to their composite pointer type (_expr.rel_).
        The result is of the composite pointer type.

      --The second and third operands have pointer to member  type,  or  one
        has pointer to member type and the other is a null pointer constant;
        pointer to member conversions (_conv.mem_) and qualification conver-
        sions  (_conv.qual_)  are  performed to bring them to a common type,
        whose cv-qualification shall match the  cv-qualification  of  either

        the  second or the third operand.  The result is of the common type.

      5.17  Assignment operators                                  [expr.ass]

    1 There are several assignment operators, all of which  group  right-to-
      left.   All require a modifiable lvalue as their left operand, and the
      type of an assignment expression is that of  its  left  operand.   The
      result  of  the  assignment  operation is the value stored in the left
      operand after the assignment has taken place; the result is an lvalue.
              assignment-expression:
                      conditional-expression
                      logical-or-expression assignment-operator assignment-expression
                      throw-expression
              assignment-operator: one of
                      =  *=  /=  %=   +=  -=  >>=  <<=  &=  ^=  |=

    2 In simple assignment (=), the value of the expression replaces that of
      the object referred to by the left operand.

    3 If the left operand is not of class type, the expression is implicitly
      converted (_conv_) to the cv-unqualified type of the left operand.

    4 If  the  left  operand  is of class type, the class shall be complete.
      Assignment to objects of a class is defined  by  the  copy  assignment
      operator (_class.copy_, _over.ass_).

    5 [Note:  For  class  objects,  assignment is not in general the same as
      initialization (_dcl.init_, _class.ctor_, _class.init_, _class.copy_).
      ]

    6 When the left operand of an assignment operator denotes a reference to
      T, the operation assigns to the object of type T denoted by the refer-
      ence.

    7 The  behavior  of an expression of the form E1 op= E2 is equivalent to
      E1=E1 op E2 except that E1 is evaluated only once.  In += and  -=,  E1
      shall  either  have  arithmetic type or be a pointer to a possibly cv-
      qualified completely defined object type.   In  all  other  cases,  E1
      shall have arithmetic type.

    8 If the value being stored in an object is accessed from another object
      that overlaps in any way the storage of the  first  object,  then  the
      overlap  shall  be exact and the two objects shall have the same type,
      otherwise the behavior is undefined.

      5.18  Comma operator                                      [expr.comma]

    1 The comma operator groups left-to-right.
              expression:
                      assignment-expression
                      expression , assignment-expression
      A pair of expressions separated by a comma is evaluated  left-to-right
      and  the  value  of  the left expression is discarded.  The lvalue-to-
      rvalue (_conv.lval_), array-to-pointer (_conv.array_),  and  function-

      to-pointer  (_conv.func_)  standard conversions are not applied to the
      left expression.  All side effects  (_intro.execution_)  of  the  left
      expression,  except  for the destruction of temporaries (_class.tempo-
      rary_), are performed before the evaluation of the  right  expression.
      The  type  and value of the result are the type and value of the right
      operand; the result is an lvalue if its right operand is.

    2 In contexts where comma is given a special meaning, [Example: in lists
      of  arguments  to  functions  (_expr.call_)  and lists of initializers
      (_dcl.init_) ] the comma operator as  described  in  this  clause  can
      appear only in parentheses.  [Example:
              f(a, (t=3, t+2), c);
      has three arguments, the second of which has the value 5.  ]

      5.19  Constant expressions                                [expr.const]

    1 In  several places, C++ requires expressions that evaluate to an inte-
      gral  or  enumeration  constant:   as   array   bounds   (_dcl.array_,
      _expr.new_), as case expressions (_stmt.switch_), as bit-field lengths
      (_class.bit_), as enumerator initializers (_dcl.enum_), as static mem-
      ber initializers (_class.static.data_), and as integral or enumeration
      non-type template arguments (_temp.arg_).
              constant-expression:
                      conditional-expression
      An integral constant-expression can involve only  literals  (_lex.lit-
      eral_),  enumerators,  const variables or static data members of inte-
      gral  or  enumeration  types  initialized  with  constant  expressions
      (_dcl.init_),  non-type template parameters of integral or enumeration
      types, and sizeof expressions.   Floating  literals  (_lex.fcon_)  can
      appear  only  if they are cast to integral or enumeration types.  Only
      type conversions to integral or enumeration types  can  be  used.   In
      particular,  except  in  sizeof expressions, functions, class objects,
      pointers, or references shall not be used, and assignment,  increment,
      decrement, function-call, or comma operators shall not be used.

    2 Other  expressions  are  considered  constant-expressions only for the
      purpose     of     non-local     static     object      initialization
      (_basic.start.init_).  Such constant expressions shall evaluate to one
      of the following:

      --a null pointer value (_conv.ptr_),

      --a null member pointer value (_conv.mem_),

      --an arithmetic constant expression,

      --an address constant expression,

      --a reference constant expression,

      --an address constant expression for a complete object type,  plus  or
        minus an integral constant expression, or

      --a pointer to member constant expression.

    3 An arithmetic constant expression shall have arithmetic or enumeration
      type  and  shall  only  have  operands  that  are   integer   literals
      (_lex.icon_),  floating  literals (_lex.fcon_), enumerators, character
      literals (_lex.ccon_) and sizeof  expressions  (_expr.sizeof_).   Cast
      operators  in  an  arithmetic  constant  expression shall only convert
      arithmetic or enumeration types to arithmetic  or  enumeration  types,
      except as part of an operand to the sizeof operator.

    4 An  address  constant expression is a pointer to an lvalue designating
      an object of static storage duration, a string literal (_lex.string_),
      or  a  function.   The  pointer shall be created explicitly, using the
      unary & operator, or implicitly using a non-type template parameter of
      pointer  type, or using an expression of array (_conv.array_) or func-
      tion (_conv.func_) type.  The subscripting operator [] and  the  class
      member  access  .   and -> operators, the & and * unary operators, and
      pointer casts (except dynamic_casts, _expr.dynamic.cast_) can be  used
      in the creation of an address constant expression, but the value of an
      object shall not be accessed  by  the  use  of  these  operators.   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 con-
      stant expression, even if the function is inline and has  a  reference
      return type.

    5 A  reference constant expression is an lvalue designating an object of
      static storage duration, a non-type template  parameter  of  reference
      type,  or  a function.  The subscripting operator [], the class member
      access .  and -> operators, the & and * unary operators, and reference
      casts   (except   those  invoking  user-defined  conversion  functions
      (_class.conv.fct_) and except dynamic_casts (_expr.dynamic.cast_)) can
      be  used  in  the creation of a reference constant expression, but the
      value of an object shall not be accessed by the use of these operators
      An  lvalue expression that designates a member or base class of a non-
      POD class object (_class_) is  not  a  reference  constant  expression
      (_class.cdtor_).  Function calls shall not be used in a reference con-
      stant expression, even if the function is inline and has  a  reference
      return type.

    6 A  pointer  to  member  constant expression shall be created using the
      unary & operator applied to a qualified-id operand  (_expr.unary.op_),
      optionally  preceded by a pointer to member cast (_expr.static.cast_).