______________________________________________________________________

  5   Expressions                                                 [expr]

  ______________________________________________________________________

1 [Note: Clause _expr_ defines the  syntax,  order  of  evaluation,  and
  meaning  of expressions.  An expression is a sequence of operators and
  operands that specifies a computation.  An expression can result in  a
  value and can cause side effects.

2 Operators  can  be  overloaded, that is, given meaning when applied to
  expressions  of  class  type  (clause  _class_)  or  enumeration  type
  (_dcl.enum_).  Uses of overloaded operators are transformed into func-
  tion calls as described in _over.oper_.  Overloaded operators obey the
  rules  for  syntax specified in clause _expr_, but the requirements of
  operand type, lvalue, and evaluation order are replaced by  the  rules
  for  function  call.  Relations between operators, such as ++a meaning
  a+=1, are not guaranteed for overloaded operators  (_over.oper_),  and
  are not guaranteed for operands of type bool.   --end note]

3 Clause  _expr_  defines the effects of operators when applied to types
  for which they have not been overloaded.  Operator  overloading  shall
  not  modify  the rules for the built-in operators, that is, for opera-
  tors applied to types for which they are  defined  by  this  Standard.
  However,  these built-in operators participate in overload resolution,
  and as part of that process user-defined conversions will  be  consid-
  ered  where necessary to convert the operands to types appropriate for
  the built-in operator If a built-in operator is selected, such conver-
  sions  will be applied to the operands before the operation is consid-
  ered  further  according  to  the  rules   in   clause   _expr_;   see
  _over.match.oper_, _over.built_.

4 Except  where noted, the order of evaluation of operands of individual
  operators and subexpressions of individual expressions, and the  order
  in  which side effects take place, is unspecified.  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 unspecified
  i = 7, i++, i++;                // i becomes 9

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

5 If during the evaluation of an expression, the result is not mathemat-
  ically defined or not in the range of  representable  values  for  its
  type,  the  behavior is undefined, unless such an expression is a con-
  stant expression (_expr.const_), in which case  the  program  is  ill-
  formed.   [Note:  most  existing implementations of C++ ignore integer
  overflows.  Treatment of division by zero, forming a remainder using a
  zero  divisor,  and all floating point exceptions vary among machines,
  and is usually adjustable by a library function.  ]

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

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

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

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

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

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

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

  --Otherwise, the integral promotions (_conv.prom_) shall be  performed
    on both operands.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
  _________________________
  1)  As a consequence, operands of type bool, wchar_t, or an enumerated
  type are converted to some integral type.

    operands shall be converted to unsigned long int.

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

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

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

10The  values  of  the  floating  operands  and  the results of floating
  expressions may be represented in greater  precision  and  range  than
  that required by the type; the types are not changed thereby.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
          ( expression )
          id-expression

  id-expression:
          unqualified-id
          qualified-id

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

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

3 The keyword this names a pointer to the object for which  a  nonstatic
  member  function (_class.this_) is invoked.  The keyword this shall be
  used only inside a nonstatic class member function body (_class.mfct_)
  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.

  _________________________
  2) The cast and assignment operators must still perform their specific
  conversions as described in _expr.cast_, _expr.static.cast_  and  _ex-
  pr.ass_.

4 The operator :: followed by an identifier, a qualified-id, or an oper-
  ator-function-id  is  a  primary-expression.  Its type is specified by
  the declaration of the identifier, qualified-id, or operator-function-
  id.  The result is the entity denoted by the identifier, qualified-id,
  or operator-function-id.  The result is an lvalue if the entity  is  a
  function or variable.  The identifier, qualified-id, or operator-func-
  tion-id shall have global namespace scope  or  be  visible  in  global
  scope because of a using-directive (_namespace.udir_).  [Note: the use
  of :: allows a type, an object, a function, an enumerator, or a names-
  pace  declared  in  the global namespace to be referred to even if its
  identifier has been hidden (_basic.lookup.qual_).  ]

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

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

7 An  identifier  is  an  id-expression  provided  it  has been suitably
  declared (clause _dcl.dcl_).  [Note:  for  operator-function-ids,  see
  _over.oper_;  for  conversion-function-ids,  see _class.conv.fct_; for
  template-ids, see _temp.names_.  A class-name prefixed by ~ denotes  a
  destructor;  see  _class.dtor_.   Within the definition of a nonstatic
  member function, an identifier that names a nonstatic member is trans-
  formed  to  a class member access expression (_class.mfct.nonstatic_).
  ] The type of the expression is  the  type  of  the  identifier.   The
  result  is  the  entity  denoted  by the identifier.  The result is an
  lvalue if the entity is a function, variable, or data member.

8 qualified-id:
          ::opt nested-name-specifier templateopt unqualified-id
          :: identifier
          :: operator-function-id
          :: template-id

  nested-name-specifier:
          class-or-namespace-name :: nested-name-specifieropt

  class-or-namespace-name:
          class-name
          namespace-name
  A nested-name-specifier that names a class, optionally followed by the
  keyword  template (_temp.arg.explicit_), and then followed by the name
  of a member of either that class (_class.mem_)  or  one  of  its  base
  classes  (clause  _class.derived_),  is  a  qualified-id; _class.qual_
  describes name 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
  member.  The result is an lvalue if the  member  is  a  static  member
  function  or  a data member.  [Note: a class member can be referred to
  using  a  qualified-id  at  any   point   in   its   potential   scope

  (_basic.scope.class_).   ] Where class-name :: class-name is used, and
  the two class-names refer to the same class, this notation  names  the
  constructor (_class.ctor_).  Where class-name :: ~ class-name is used,
  the two class-names shall refer to the same class; this notation names
  the  destructor  (_class.dtor_).   [Note:  a typedef-name that names a
  class is a class-name (_dcl.typedef_).  Except as  the  identifier  in
  the declarator for a constructor or destructor definition outside of a
  class member-specification (_class.ctor_,  _class.dtor_),  a  typedef-
  name  that  names  a class may be used in a qualified-id to refer to a
  constructor or destructor.  ]

9 A nested-name-specifier that names  a  namespace  (_basic.namespace_),
  followed  by  the name of a member of that namespace (or the name of a
  member of a namespace made visible by a using-directive ) is a  quali-
  fied-id; _namespace.qual_ describes name 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
  _temp.explicit_, _temp.spec_, and _temp.class.spec_.

  5.2  Postfix expressions                                   [expr.post]

1 Postfix expressions group left-to-right.

  postfix-expression:
          primary-expression
          postfix-expression [ expression ]
          postfix-expression ( expression-listopt )
          simple-type-specifier ( expression-listopt )
          postfix-expression . templateopt id-expression
          postfix-expression -> templateopt id-expression
          postfix-expression . 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
  (clause  _over_),  in  which  case  the  appropriate function shall be
  selected according to the rules in _over.match_.  The function  called
  in a member function call is normally selected according to the static
  type of the object expression (clause _class.derived_),  but  if  that
  function is virtual and is not specified using a qualified-id then the
  function actually called will be the final overrider (_class.virtual_)
  of  the selected function in the dynamic type of the object expression
  [Note: the dynamic type is the type of the object pointed or  referred
  to  by  the  current  value  of  the object expression.  _class.cdtor_
  describes the behavior of virtual  function  calls  when  the  object-
  expression refers to an object under construction or destruction.  ]

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

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

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

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

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

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

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

9 Recursive calls are permitted,  except  to  the  function  named  main
  (_basic.start.main_).

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

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

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

  declared  constructor  (_dcl.init_,  _class.ctor_), and the expression
  T(x1, x2, ...)  is equivalent in effect to the declaration T t(x1, x2,
  ...);  for  some  invented temporary variable t, with the result being
  the value of t as an rvalue.

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

  5.2.4  Pseudo destructor call                            [expr.pseudo]

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

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

  5.2.5  Class member access                                  [expr.ref]

1 A  postfix  expression followed by a dot .  or an arrow ->, optionally
  followed by the keyword template (_temp.arg.explicit_), and then  fol-
  lowed  by  an  id-expression,  is  a  postfix expression.  The postfix
  expression before the dot or arrow is evaluated;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 (clause _class_), the name  of  a
  class  is  also  considered  a  nested member of that class.  ] [Note:
  _________________________
  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.

  _basic.lookup.classref_ describes how names are looked up after the  .
  and -> operators.  ]

3 If E1 has the type "pointer to class X," then the expression E1->E2 is
  converted  to  the  equivalent  form  (*(E1)).E2;  the  remainder   of
  _expr.ref_ will address only the first option  (dot)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  _expr.ref_,  cq  represents  either const or the absence of
  const; vq represents either volatile or the absence of  volatile.   cv
  represents   an   arbitrary   set  of  cv-qualifiers,  as  defined  in
  _basic.type.qualifier_.

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

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

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

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

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

    --Otherwise,  if  E1.E2  refers to a non-static member function, and
      the type of E2 is "function of (parameter type list) cv  returning
      T", then E1.E2 is not an lvalue.  The expression designates a non-
      static member function.  The expression can be used  only  as  the
      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".
  _________________________
  6)  Note that if E1 has the type "pointer to class X", then (*(E1)) is
  an lvalue.

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

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

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

  5.2.6  Increment and decrement                        [expr.post.incr]

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

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

  5.2.7  Dynamic cast                                [expr.dynamic.cast]

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

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

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

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

5 If T is "pointer to cv1 B" and v has type "pointer to cv2 D" such that
  B is a base class of D, the result is a pointer to the unique  B  sub-
  object of the D object pointed to by v.  Similarly, if T is "reference
  to cv1 B" and v has type cv2 D" such that B is a base class of D,  the
  result  is  an  lvalue  for  the unique7) B sub-object of the D object
  referred to by v.  In both the pointer and reference cases, cv1  shall
  _________________________

  be  the  same  cv-qualification  as, or greater cv-qualification than,
  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:

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

  class A { virtual void f(); };
  class B { virtual void g(); };
  class D : public virtual A, private B {};
  void g()
  {
      D   d;
      B*  bp = (B*)&d;            // cast needed to break protection
      A*  ap = &d;                // public derivation, no cast needed
      D&  dr = dynamic_cast<D&>(*bp);     // fails
      ap = dynamic_cast<A*>(bp);          // fails
      bp = dynamic_cast<B*>(ap);          // fails
      ap = dynamic_cast<A*>(&d);          // succeeds
      bp = dynamic_cast<B*>(&d);          // fails
  }
  class E : public D, public B {};
  class F : public E, public D {};
  void h()
  {
      F   f;
      A*  ap  = &f;                       // succeeds: finds unique A
      D*  dp  = dynamic_cast<D*>(ap);     // fails: yields 0
                                          // f has two D sub-objects
      E*  ep  = (E*)ap;                   // ill-formed:
                                          // cast from virtual base
      E*  ep1 = dynamic_cast<E*>(ap);     // succeeds
  }
    --end  example]  [Note:  _class.cdtor_  describes  the behavior of a
  dynamic_cast applied to an object under construction  or  destruction.
  ]

  5.2.8  Type identification                               [expr.typeid]

1 The  result  of  a  typeid  expression  is  an  lvalue  of  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
  _________________________
  8) If p is an expression of pointer type, then *p, (*p), *(p), ((*p)),
  *((p)), and so on all meet this requirement.

  (_conv.lval_),  array-to-pointer  (_conv.array_),   and   function-to-
  pointer  (_conv.func_)  conversions are not applied to the expression.
  If the type of the expression is a class type, the class shall be com-
  pletely-defined.  The expression is not evaluated.

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

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

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

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

  5.2.9  Static cast                                  [expr.static.cast]

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

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

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

4 Any expression can be explicitly converted  to  type  cv  void."   The
  expression  value  is discarded.  [Note: however, if the value is in a

  temporary variable (_class.temporary_), the destructor for that  vari-
  able  is not executed until the usual time, and the value of the vari-
  able is preserved for the purpose of executing the destructor.  ]  The
  lvalue-to-rvalue  (_conv.lval_),  array-to-pointer (_conv.array_), and
  function-to-pointer (_conv.func_) standard conversions are not applied
  to the expression.

5 An lvalue of type cv1 B", where B is a class type, can be cast to type
  "reference  to  cv2  D",  where  D  is   a   class   derived   (clause
  _class.derived_)  from B, if a valid standard conversion from "pointer
  to D" to "pointer to B" exists (_conv.ptr_), cv2 is the same cv-quali-
  fication  as,  or  greater  cv-qualification than, cv1, and B is not a
  virtual base class of D.  The result is an lvalue of type cv2 D."   If
  the  lvalue  of  type  cv1 B" is actually a sub-object of an object of
  type D, the lvalue refers to the enclosing object of type  D.   Other-
  wise, the result of the cast is undefined.  [Example:
  struct B {};
  struct D : public B {};
  D d;
  B &br = d;

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

6 The inverse of any standard conversion sequence (clause _conv_), other
  than    the    lvalue-to-rvalue    (_conv.lval_),     array-to-pointer
  (_conv.array_),   function-to-pointer   (_conv.func_),   and   boolean
  (_conv.bool_)  conversions,  can   be   performed   explicitly   using
  static_cast  subject  to  the restriction that the explicit conversion
  does not cast away constness (_expr.const.cast_),  and  the  following
  additional rules for specific cases:

7 A value of integral type can be explicitly converted to an enumeration
  type.  The value is unchanged if the  integral  value  is  within  the
  range  of the enumeration values (_dcl.enum_) Otherwise, the 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 (clause _class.derived_) from B, if a valid  standard  conver-
  sion from "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is
  the same cv-qualification as, or greater cv-qualification  than,  cv1,
  and  B  is  not  a  virtual  base  class of D.  The null pointer value
  (_conv.ptr_) is converted to the null pointer value of the destination
  type.   If the rvalue of type "pointer to cv1 B" points to a B that is
  actually a sub-object of an object of type D,  the  resulting  pointer
  points  to  the  enclosing object of type D.  Otherwise, the result of
  the cast is undefined.

9 An rvalue of type "pointer to member of D of type cv1 T" can  be  con-
  verted  to  an  rvalue of type "pointer to member of B of type cv2 T",
  where B is a base class (clause _class.derived_)  of  D,  if  a  valid
  standard  conversion  from  "pointer  to  member  of  B  of type T" to
  "pointer to member of D of type T" exists (_conv.mem_), and cv2 is the

  same cv-qualification as, or greater cv-qualification than, cv1.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 origi-
  nal  member, or is a base or derived class of the class containing the
  original member, the resulting pointer to member points to the  origi-
  nal  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_.  ]

10An rvalue of type "pointer to cv void" can be explicitly converted  to
  a  pointer  to object type A value of type pointer to object converted
  to "pointer to cv void" and back to the  original  pointer  type  will
  have its original value.

  5.2.10  Reinterpret cast                       [expr.reinterpret.cast]

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

2 The  reinterpret_cast  operator shall not cast away constness.  [Note:
  see _expr.const.cast_ for the  definition  of  ``casting  away  const-
  ness''.   Subject  to  the restrictions in this section, an expression
  may be cast to its own type using a reinterpret_cast operator.  ]

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

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

5 A  value  of  integral type or enumeration type can be explicitly con-
  verted  to  a  pointer.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.
  _________________________
  9)  Function types (including those used in pointer to member function
  types) are never cv-qualified; see _dcl.fct_ .
  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.

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
  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,
  _________________________
  11) The types may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.
  12) T1 and T2 may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.

  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
  const_cast  are  listed below.  No other conversion shall be performed
  explicitly using const_cast.

2 [Note: Subject to the restrictions in this section, an expression  may
  be cast to its own type using a const_cast operator.  ]

3 For two pointer types T1 and T2 where

            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.
  _________________________
  13) This is sometimes referred to as a type pun.

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
  T there does not exist an implicit conversion (clause _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.

  _________________________
  14)  const_cast  is not limited to conversions that cast away a const-
  qualifier.

  unary-expression:
          postfix-expression
          ++  cast-expression
          --  cast-expression
          unary-operator cast-expression
          sizeof unary-expression
          sizeof ( type-id )
          new-expression
          delete-expression
  unary-operator: one of
          *  &  +  -  !  ~

  5.3.1  Unary operators                                 [expr.unary.op]

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

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

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

4 The address of an object of incomplete type can be taken, but  if  the
  complete type of that object is a class type that declares operator&()
  as  a  member  function,  then  the  behavior  is  undefined  (and  no

  diagnostic is required).  The operand of & shall not be a bit-field.

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

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

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

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

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

  5.3.2  Increment and decrement                         [expr.pre.incr]

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

2 The operand of prefix -- is modified by 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
  number  of bytes in the array.  This implies that the size of an array
  of n elements is n times the size of an element.

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

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

5 Types shall not be defined in a sizeof expression.

6 The  result is a constant of type size_t.  [Note: size_t is defined in
  the standard header <cstddef>(_lib.support.types_).  ]

  5.3.4  New                                                  [expr.new]

1 The new-expression  attempts  to  create  an  object  of  the  type-id
  (_dcl.name_)  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 )
  _________________________
  15) sizeof(bool) is not required to be 1.
  16) The actual size of a base class subobject may be less than the re-
  sult  of applying sizeof to the subobject, due to virtual base classes
  and less strict padding requirements on base class subobjects.

  new-type-id:
          type-specifier-seq new-declaratoropt
  new-declarator:
          ptr-operator new-declaratoropt
          direct-new-declarator
  direct-new-declarator:
          [ expression ]
          direct-new-declarator [ constant-expression ]
  new-initializer:
          ( expression-listopt )
  Entities  created  by  a  new-expression have dynamic storage duration
  (_basic.stc.dynamic_).  [Note: the lifetime of such an entity  is  not
  necessarily  restricted to the scope in which it is created.  ] If the
  entity is a non-array object, the new-expression returns a pointer  to
  the  object  created.  If it is an array, the new-expression returns a
  pointer to the initial element of the array.

2 The new-type-id in a new-expression is the longest  possible  sequence
  of new-declarators.  [Note: this prevents ambiguities between declara-
  tor operators &, *, [], and their expression counterparts.   ]  [Exam-
  ple:
  new int * i;                    // syntax error: parsed as (new int*) i
                                  //               not as (new int)*i
  The  *  is the pointer declarator and not the multiplication operator.
  ]

3 [Note: parentheses in a new-type-id of a new-expression can have  sur-
  prising effects.  [Example:
  new int(*[10])();               // error
  is ill-formed because the binding is
  (new int) (*[10])();            // error
  Instead,  the explicitly parenthesized version of the new operator can
  be used to create objects of compound types (_basic.compound_):
  new (int (*[10])());
  allocates an array of 10 pointers to functions (taking no argument and
  returning int).  ] ]

4 The  type-specifier-seq  shall not contain class declarations, or enu-
  meration declarations.

5 When the allocated object  is  an  array  (that  is,  the  direct-new-
  declarator  syntax  is  used  or the new-type-id or type-id denotes an
  array type), the new-expression yields a pointer to the  initial  ele-
  ment  (if any) of the array.  [Note: both new int and new int[10] have
  type int* and the type of new int[i][10] is int (*)[10].  ]

6 Every constant-expression in a direct-new-declarator shall be an inte-
  gral  constant  expression  (_expr.const_)  and evaluate to a strictly
  positive value.  The expression in a direct-new-declarator shall  have
  integral type (_basic.fundamental_) with a non-negative value.  [Exam-
  ple: if n is a variable of type int,  then  new float[n][5]  is  well-
  formed  (because  n is the expression of a direct-new-declarator), but
  new float[5][n] is ill-formed (because n  is  not  a  constant-expres-
  sion).   If n is negative, the effect of new float[n][5] is undefined.

  ]

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

8 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.  If the object being created is not an
  array, the size requested shall be the size of  the  object.   If  the
  object  is an array, the size requested may be larger than the size of
  the object.  For arrays of char  and  unsigned  char,  the  difference
  between  the  result of the new expression and the address returned by
  the allocation function shall be an  integral  multiple  of  the  most
  stringent  alignment  requirement  (_basic.types_)  of any object type
  whose size is no greater than the size of  the  array  being  created.
  [Note:  since  allocation  functions are assumed to return pointers to
  storage that is appropriately aligned for objects of  any  type,  this
  constraint  on  array  allocation overhead permits the common idiom of
  allocating character arrays into which objects  of  other  types  will
  later be placed.  ]

9 An  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.   [Note:  If  the  library allocation function is called, it will
  either return null or a pointer to a block of storage in  which  space
  for  the  object  shall  have  been reserved.  The block of storage is
  assumed to be appropriately aligned and  of  the  requested  size  The
  address of the created object will not necessarily be the same as that
  of the block of storage if the object is an array.  ]

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

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

12[Note: unless an allocation function is declared with an empty  excep-
  tion-specification  (_except.spec_),  throw(), it indicates failure to
  allocate storage by throwing a bad_alloc exception  (clause  _except_,
  _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo-
  cation function is declared  with  an  empty  exception-specification,
  throw(), it returns null to indicate failure to allocate storage and a
  non-null pointer otherwise.   --end note] If the  allocation  function
  returns null, initialization shall not be done, the deallocation func-
  tion shall not be called, and the value of the new-expression shall be
  null.

13[Note:  when  the allocation function returns a value other than null,
  it shall be a pointer to a block of storage in  which  space  for  the
  object  shall  have been reserved.  the block of storage is assumed to
  be appropriately aligned and of the requested size The address of  the
  created  object  will not necessarily be the same as that of the block
  if the object is an array.  ]

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

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

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

18A  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
  except the first are identical.

19If placement operator delete is called, it is passed  the  same  addi-
  tional  arguments  as  were passed to placement operator new; that is,
  the same arguments as those specified with the  new-placement  syntax.
  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.

20Whether  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
  _________________________
  17)  This  may  include  evaluating a new-initializer and/or calling a
  constructor.

  unspecified whether the arguments to a constructor  are  evaluated  if
  the  allocation  function  returns  the null pointer or exits using an
  exception.

  5.3.5  Delete                                            [expr.delete]

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

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

3 In  the  first  alternative (delete object), if the static type of the
  operand is different from its dynamic type, the static type shall be a
  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
  _________________________
  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.
  19) This implies that an object cannot be deleted using a  pointer  of
  type void* because there are no objects of type void.

  rendering the pointer invalid.  [Note: the value  of  a  pointer  that
  refers to deallocated storage is indeterminate.  ]

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

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

7 The    delete-expression    will    call   a   deallocation   function
  (_basic.stc.dynamic.deallocation_).

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

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 example,
  struct S {
          mutable int i;
  };
  const S cs;
  int S::* pm = &S::i;            // pm refers to mutable member S::i
  cs.*pm = 88;                    // ill-formed: cs is a const object
  ]

6 If  the  result  of  .*  or ->* is a function, then that result can be
  used only as the operand for the function call operator ().  [Example:
  (ptr_to_obj->*ptr_to_mfct)(10);
  calls  the  member  function  denoted  by  ptr_to_mfct  for the object
  pointed to by ptr_to_obj.  ] The result of  a  .*   expression  is  an
  lvalue  only  if its first operand is an lvalue and its second operand
  is a pointer to data member.  The result of an ->*  expression  is  an
  lvalue only if its second operand is a pointer to data member.  If the
  second operand is the null pointer to member value  (_conv.mem_),  the
  behavior is undefined.

  5.6  Multiplicative operators                               [expr.mul]

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

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

3 The binary * operator indicates multiplication.

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

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

  (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)

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.

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

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

  5.8  Shift operators                                      [expr.shift]

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

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

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

  5.9  Relational operators                                   [expr.rel]

1 The relational operators group left-to-right.  [Example:  a<b<c  means
  (a<b)<c and not (a<b)&&(b<c).  ]
  relational-expression:
          shift-expression
          relational-expression < shift-expression
          relational-expression > shift-expression
          relational-expression <= shift-expression
          relational-expression >= shift-expression
  The  operands shall have arithmetic, enumeration or pointer type.  The
  operators < (less than), > (greater than), <= (less than or equal to),
  and  >=  (greater than or equal to) all yield false or true.  The type
  of the result is bool.

2 The usual arithmetic conversions are performed on operands  of  arith-
  metic or enumeration type.  Pointer conversions (_conv.ptr_) and qual-
  ification conversions (_conv.qual_) are performed on pointer  operands
  (or on a pointer operand and a null pointer constant) to bring them to
  their composite pointer type.  If one operand is a null  pointer  con-
  stant,  the  composite  pointer  type is the type of the other operand
  Otherwise, if one of the operands has type "pointer to cv1 void", then
  the  other  has type "pointer to cv2 T" and the composite pointer type
  is "pointer to cv12 void", where cv12 is the union  of  cv1  and  cv2.
  Otherwise,  the  composite  pointer  type  is  a  pointer type similar
  (_conv.qual_) to the type of one of the operands, with a cv-qualifica-
  tion signature (_conv.qual_) that is the union of the cv-qualification

  signatures of the operand types.  [Note: this implies that any pointer
  can be compared to a null pointer constant and that any object pointer
  can be compared to a  pointer  to  (possibly  cv-qualified)  void.   ]
  [Example:
  void *p;
  const int *q;
  int **pi;
  const int *const *pci;
  void ct()
  {
      p <= q;                     // Both converted to const void * before comparison
      pi <= pci;                  // Both converted to const int *const * before comparison
  }
    --end  example]  Pointers  to  objects or functions of the same type
  (after pointer conversions) can be compared, with a result defined  as
  follows:

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

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

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

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

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

  --Other pointer comparisons are unspecified.

  5.10  Equality operators                                     [expr.eq]

1 equality-expression:
          relational-expression
          equality-expression == relational-expression
          equality-expression != relational-expression
  The  ==  (equal  to) and the != (not equal to) operators have the same
  semantic restrictions, conversions, and result type as the  relational

  operators  except  for  their lower precedence and truth-value result.
  [Note: a<b == c<d is true whenever a<b and c<d have  the  same  truth-
  value.   ]  Pointers  to  objects or functions of the same type (after
  pointer conversions) can be compared for equality.   Two  pointers  of
  the  same  type  compare equal if and only if they are both null, both
  point to the same object or function, or both point one past  the  end
  of the same array.

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

  5.11  Bitwise AND operator                              [expr.bit.and]

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

  5.12  Bitwise exclusive OR operator                         [expr.xor]

1 exclusive-or-expression:
          and-expression
          exclusive-or-expression ^ and-expression
  The  usual  arithmetic  conversions  are  performed; the result is the

  bitwise exclusive function of the operands.  The operator applies only
  to integral or enumeration operands.

  5.13  Bitwise inclusive OR operator                          [expr.or]

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

  5.14  Logical AND operator                              [expr.log.and]

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

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

  5.15  Logical OR operator                                [expr.log.or]

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

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

  5.16  Conditional operator                                 [expr.cond]

1 conditional-expression:
          logical-or-expression
          logical-or-expression ? expression : assignment-expression
  Conditional  expressions group right-to-left.  The first expression is
  implicitly converted to bool (clause _conv_).  It is evaluated and  if
  it  is  true, the result of the conditional expression is the value of
  the second expression, otherwise that of the  third  expression.   All
  side  effects of the first expression except for destruction of tempo-
  raries (_class.temporary_) happen before the second or  third  expres-
  sion  is  evaluated.   Only one of the second and third expressions is

  evaluated.

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

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

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

3 Otherwise, if the second and third operand have different  types,  and
  either  has  (possibly cv-qualified) class type, an attempt is made to
  convert each of those operands to the type of the  other  The  process
  for  determining  whether  an  operand expression E1 of type T1 can be
  converted to match an operand expression E2 of type T2 is  defined  as
  follows:

  --If  E2  is  an  lvalue: E1 can be converted to match E2 if E1 can be
    implicitly converted (clause _conv_) to the type "reference to  T2",
    subject  to the constraint that in the conversion the reference must
    bind directly (_dcl.init.ref_) to E1.

  --If E2 is an rvalue, or if the conversion above cannot be done:

    --if E1 and E2 have class type, and the underlying class  types  are
      the  same or one is a base class of the other: E1 can be converted
      to match E2 if the class of T2 is the same  type  as,  or  a  base
      class  of,  the class of T1, and the cv-qualification of T2 is the
      same cv-qualification as, or a greater cv-qualification than,  the
      cv-qualification  of  T1.   If  the  conversion  is applied, E1 is
      changed to an rvalue of type T2 that still refers to the  original
      source  class  object  (or  the  appropriate  subobject  thereof).
      [Note: that is, no copy is made.  ]

    --Otherwise (i.e., if E1 or E2 has a nonclass type, or if they  both
      have  class  types  but  the underlying classes are not either the
      same or one a base class of the other): E1  can  be  converted  to
      match  E2  if  E1  can  be  implicitly  converted to the type that
      expression E2 would have if E2 were converted to an rvalue (or the
      type it has, if E2 is an rvalue).

  Using this process, it is determined whether the second operand can be
  converted to match the third operand, and whether  the  third  operand
  can be converted to match the second operand If both can be converted,
  or one can be converted but the conversion is ambiguous,  the  program
  is  ill-formed.   If  neither  can be converted, the operands are left
  unchanged and further checking is  performed  as  described  below  If

  exactly  one conversion is possible, that conversion is applied to the
  chosen operand and the converted operand is used in place of the orig-
  inal operand for the remainder of this section.

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

5 Otherwise, the result is an rvalue.  If the second and  third  operand
  do  not  have  the  same  type, and either has (possibly cv-qualified)
  class type, overload resolution is used to determine  the  conversions
  (if   any)   to   be   applied  to  the  operands  (_over.match.oper_,
  _over.built_).  If the overload resolution fails, the program is  ill-
  formed.   Otherwise,  the conversions thus determined are applied, and
  the converted operands are used in place of the original operands  for
  the remainder of this section.

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

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

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

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

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

  5.17  Assignment operators                                  [expr.ass]

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

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

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

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

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

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

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

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

  5.18  Comma operator                                      [expr.comma]

1 The comma operator groups left-to-right.
  expression:
          assignment-expression
          expression , assignment-expression
  A pair of expressions separated by a comma is evaluated  left-to-right
  and  the  value  of  the left expression is discarded.  The lvalue-to-
  rvalue (_conv.lval_), array-to-pointer (_conv.array_),  and  function-
  to-pointer  (_conv.func_)  standard conversions are not applied to the
  left expression.  All side effects  (_intro.execution_)  of  the  left
  expression,  except  for the destruction of temporaries (_class.tempo-
  rary_), are performed before the evaluation of the  right  expression.
  The  type  and value of the result are the type and value of the right
  operand; the result is an lvalue if its right operand is.

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

  5.19  Constant expressions                                [expr.const]

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

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

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

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

  --an arithmetic constant expression,

  --an address constant expression,

  --a reference constant expression,

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

  --a pointer to member constant expression.

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

4 An  address  constant expression is a pointer to an lvalue designating
  an object of static storage duration, a string literal (_lex.string_),
  or  a  function.   The  pointer shall be created explicitly, using the
  unary & operator, or implicitly using a non-type template parameter of
  pointer  type,  or  using  an  expression  of  array (_conv.array_) or

  function  (_conv.func_)  type.   The  subscripting operator [] and the
  class member access .  and -> operators, the & and * unary  operators,
  and  pointer  casts (except dynamic_casts, _expr.dynamic.cast_) can be
  used in the creation of an address constant expression, but the  value
  of  an object shall not be accessed by the use of these operators.  If
  the subscripting operator is used, one of its  operands  shall  be  an
  integral  constant  expression.   An  expression  that  designates the
  address of a member or base class of a non-POD  class  object  (clause
  _class_) is not an address constant expression (_class.cdtor_).  Func-
  tion calls shall not be used in an address constant  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  opera-
  tors.  If the subscripting operator is used, one of its operands shall
  be an integral constant expression.  An lvalue expression that  desig-
  nates  a  member  or  base  class  of  a  non-POD class object (clause
  _class_) is  not  a  reference  constant  expression  (_class.cdtor_).
  Function  calls  shall not be used in a reference constant expression,
  even if the function is inline and has a reference return type.

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