______________________________________________________________________

  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  con-
  versions  will be applied to the operands before the operation is con-
  sidered  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.1) 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:

  _________________________
  1)  The  precedence of operators is not directly specified, but it can
  be derived from the syntax.

  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.2)
  _________________________
  2) As a consequence, operands of type bool, wchar_t, or an  enumerated
  type are converted to some integral type.

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

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

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

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

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

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

  5.1  Primary expressions                                   [expr.prim]

1 Primary expressions are literals, names, and names  qualified  by  the
  scope resolution operator ::.
  primary-expression:
          literal
          this
          ( 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_)
  _________________________
  3) The cast and assignment operators must still perform their specific
  conversions  as  described in _expr.cast_, _expr.static.cast_ and _ex-
  pr.ass_.

  or in a constructor mem-initializer (_class.base.init_).  The type  of
  the  expression  is  a pointer to the function's class (_class.this_),
  possibly with cv-qualifiers on the class type.  The expression  is  an
  rvalue.

4 The operator :: followed by an identifier, a qualified-id, or an oper-
  ator-function-id is a primary-expression.  Its type  is  specified  by
  the declaration of the identifier, qualified-id, or operator-function-
  id.  The result is the entity denoted by the identifier, qualified-id,
  or  operator-function-id.   The result is an lvalue if the entity is a
  function or variable.  The identifier, qualified-id, or operator-func-
  tion-id  shall  have  global  namespace  scope or be visible in global
  scope because of a using-directive (_namespace.udir_).  [Note: the use
  of :: allows a type, an object, a function, an enumerator, or a names-
  pace declared in the global namespace to be referred to  even  if  its
  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 :: template nested-name-specifier

  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 lookup 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 lookup 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 )
          typename ::opt  nested-name-specifier identifier ( expression-listopt )
          typename ::opt  nested-name-specifier templateopt  template-id ( 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-specifier template template-id :: ~ 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.4) 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  function5)  (_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
  _________________________
  4) This is true even if the subscript operator is used in the  follow-
  ing common idiom: &x[0].
  5) A static member function (_class.static_) is an ordinary  function.

  function  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
  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;6) 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
  _________________________
  6) 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.

  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:
  _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)7).  Abbreviating
  object-expression.id-expression as E1.E2, then  the  type  and  lvalue
  properties  of  this  expression  are  determined  as follows.  In the
  remainder of _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
  _________________________
  7) Note that if E1 has the type "pointer to class X", then (*(E1))  is
  an lvalue.

      left-hand  operand  of  a  member  function  call  (_class.mfct_).
      [Note: any redundant set of parentheses surrounding the expression
      is ignored (_expr.prim_).  ] The type of  E1.E2  is  "function  of
      (parameter type list) cv returning T".

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

  --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 unique8) 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:

  _________________________
  8)  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  static  type  const
  std::type_info (_lib.type.info_) and dynamic type const std::type_info
  or const name where name is an  implementation-defined  class  derived
  from   std::type_info   which  preserves  the  behavior  described  in
  _lib.type.info_.9) The lifetime of  the  object  referred  to  by  the
  lvalue extends to the end of the program.  Whether or not the destruc-
  tor 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  pointer10)  and  the  pointer is a null pointer value
  (_conv.ptr_), the typeid expression throws  the  bad_typeid  exception
  (_lib.bad.typeid_).
  _________________________
  9) The recommended name for such a class is extended_type_info.
  10) If p is an expression  of  pointer  type,  then  *p,  (*p),  *(p),
  ((*p)), *((p)), and so on all meet this requirement.

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

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

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 result-
  ing 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.11)
  The  null  member  pointer value (_conv.mem_) is converted to the null
  member pointer value of the destination type.  If class B contains the
  original member, or is a base or derived class of the class containing
  the original member, the resulting pointer to  member  points  to  the
  original  member.   Otherwise,  the  result  of the cast is undefined.
  [Note: although class B need not  contain  the  original  member,  the
  dynamic  type of the object on which the pointer to member is derefer-
  enced 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.12) A pointer converted to an integer of suffi-
  cient size (if any such exists on the implementation) and back to  the
  _________________________
  11) Function types (including those used in pointer to member function
  types) are never cv-qualified; see _dcl.fct_ .
  12) 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.

  same  pointer  type  will  have  its  original value; mappings between
  pointers and integers are otherwise implementation-defined.

6 A pointer to a function can be explicitly converted to a pointer to  a
  function  of  a  different  type.   The  effect  of calling a function
  through a pointer to a function type (_dcl.fct_) that is not the  same
  as  the  type  used  in  the  definition of the function is undefined.
  Except that converting an rvalue of type "pointer to T1" to  the  type
  "pointer  to  T2" (where T1 and T2 are function types) and back to its
  original type yields the original pointer value, the result of such  a
  pointer  conversion  is  unspecified.   [Note: see also _conv.ptr_ for
  more details of pointer conversions.  ]

7 A pointer to an object can be explicitly converted to a pointer to  an
  object of different type.13) 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.14) 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.

10An lvalue expression of type T1 can be cast to the type "reference  to
  T2"  if  an  expression of type "pointer to T1" can be explicitly con-
  verted to the type "pointer to T2" using a reinterpret_cast.  That is,
  a  reference  cast  reinterpret_cast<T&>(x) has the same effect as the
  conversion *reinterpret_cast<T*>(&x) with the built-in & and *  opera-
  tors.   The  result is an lvalue that refers to the same object as the
  source lvalue, but with a different type.  No temporary is created, no
  _________________________
  13) The types may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.
  14) T1 and T2 may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.

  copy  is made, and constructors (_class.ctor_) or conversion functions
  (_class.conv_) are not called.15)

  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.

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-qualifier16) may produce undefined
  _________________________
  15) This is sometimes referred to as a type pun.

  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.

  _________________________
  16) 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 subtracting 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.17) ] [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.18) 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_) or new-type-id to which it is applied.  The type of  that
  object  is  the  allocated type.  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 cre-
  ated 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 )
  _________________________
  17) sizeof(bool) is not required to be 1.
  18) 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 A  new-expression obtains storage for the object by calling an alloca-
  tion function (_basic.stc.dynamic.allocation_).  If the new-expression
  terminates by throwing an exception, it may release storage by calling
  a deallocation function  (_basic.stc.dynamic.deallocation_).   If  the
  allocated  type is a non-array type, the allocation function's name is
  operator new and the deallocation function's name is  operator delete.
  If the allocated type is an array type, the allocation function's name
  is  operator new[]   and   the   deallocation   function's   name   is
  operator delete[].   [Note:  an  implementation  shall provide default
  definitions for the global allocation functions  (_basic.stc.dynamic_,
  _lib.new.delete.single_,  _lib.new.delete.array_).   A C++ program can
  provide alternative  definitions  of  these  functions  (_lib.replace-
  ment.functions_) and/or class-specific versions (_class.free_).  ]

9 If  the new-expression begins with a unary :: operator, the allocation
  function's name is looked up in the global scope.  Otherwise,  if  the
  allocated  type  is  a  class  type T or array thereof, the allocation
  function's name is looked up in the scope of T.  If this lookup  fails
  to  find  the  name, or if the allocated type is not a class type, the
  allocation function's name is looked up in the global scope.

10A new-expression passes the amount of space requested to  the  alloca-
  tion  function  as the first argument of type std::size_t.  That argu-
  ment shall be no less than the size of the object  being  created;  it
  may  be  greater than the size of the object being created only if the
  object is an array.  For arrays of char and unsigned char, the differ-
  ence 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:  Because 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.  ]

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

12[Example:

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

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

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

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

  Here,  x  and y are non-negative unspecified values representing array
  allocation overhead; the result of the new-expression will  be  offset
  by  this amount from the value returned by operator new[].  This over-
  head may be applied in all array new-expressions, including those ref-
  erencing  the  library function operator new[](std::size_t, void*) and
  other placement allocation functions.  The amount of overhead may vary
  from one invocation of new to another.  ]

13[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
  allocation function is declared with an empty exception-specification,
  throw(), it returns null to indicate failure to allocate storage and a
  non-null  pointer  otherwise.   ]  If  the allocation function returns
  null, initialization shall not  be  done,  the  deallocation  function
  shall  not  be  called,  and  the value of the new-expression shall be
  null.

14[Note: when the allocation function returns a value other  than  null,
  it  must  be  a  pointer  to a block of storage in which space for the
  object has 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.  ]

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

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

17If any part of the object initialization described above19) terminates
  by throwing an exception and a suitable deallocation function  can  be
  found, the deallocation function 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.  If no unambiguous
  matching deallocation function can be found, propagating the exception
  does not cause the object's memory to be freed.  [Note: This is appro-
  priate when the called allocation function does not  allocate  memory;
  otherwise, it is likely to result in a memory leak.  ]

18If  the  new-expression begins with a unary :: operator, the dealloca-
  tion function's name is looked up in the global scope.  Otherwise,  if
  the  allocated type is a class type T or an array thereof, the deallo-
  cation function's name is looked up in the scope of T.  If this lookup
  fails  to  find the name, or if the allocated type is not a class type
  or array thereof, the deallocation function's name is looked up in the
  global scope.

19A  declaration of a placement deallocation function matches the decla-
  ration of a placement allocation function if it has the same number of
  parameters  and,  after  parameter  transformations  (_dcl.fct_),  all
  parameter types except the first  are  identical.   Any  non-placement
  deallocation function matches a non-placement allocation function.  If
  the lookup finds a single matching deallocation function,  that  func-
  tion  will  be  called;  otherwise,  no  deallocation function will be
  called.

20If a new-expression calls a deallocation function, it passes the value
  returned  from  the  allocation function call as the first argument of
  _________________________
  19) This may include evaluating a  new-initializer  and/or  calling  a
  constructor.

  type void*.  If a placement deallocation function  is  called,  it  is
  passed  the  same additional arguments as were passed to the placement
  allocation function, that is, the same arguments  as  those  specified
  with  the  new-placement  syntax.  If the implementation is allowed to
  make a copy of any argument as part of  the  call  to  the  allocation
  function, it is allowed to make a copy (of the same original value) as
  part of the call to the deallocation function or  to  reuse  the  copy
  made  as  part of the call to the allocation function.  If the copy is
  elided in one place, it need not be elided in the other.

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

  5.3.5  Delete                                            [expr.delete]

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

2 If the operand has a class type, the operand is converted to a pointer
  type by calling the above-mentioned conversion function, and the  con-
  verted  operand  is  used  in  place  of  the original operand for the
  remainder of this section.  In either alternative, if the value of the
  operand of delete is the null pointer the operation has no effect.  In
  the first alternative (delete object), the value  of  the  operand  of
  delete shall be a pointer to a non-array object 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.20) 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
  _________________________
  20) 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.

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

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

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

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

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

8 [Note:  An  implementation  provides default definitions of the global
  deallocation    functions     operator delete()     for     non-arrays
  (_lib.new.delete.single_)    and    operator delete[]()   for   arrays
  (_lib.new.delete.array_).  A C++ program can provide alternative defi-
  nitions   of  these  functions  (_lib.replacement.functions_),  and/or
  class-specific versions (_class.free_).  ] When the keyword delete  in
  a  delete-expression  is 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.

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

  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

    converted to a pointer to member of an unambiguous non-virtual  base
    class type;

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

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

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

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

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

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

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

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

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

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

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

6 When two pointers to elements of the same array object are subtracted,
  the  result  is the difference of the subscripts of the two array ele-
  ments.  The type of the result  is  an  implementation-defined  signed
  integral  type;  this  type  shall be the same type that is defined as
  ptrdiff_t in the <cstddef> header (_lib.support.types_).  As with  any
  other  arithmetic  overflow,  if  the result does not fit in the space
  provided, the behavior is undefined.  In other words, if  the  expres-
  sions P and Q point to, respectively, the i-th and j-th elements of an
  array object, the expression (P)-(Q) has the value  i-j  provided  the
  value  fits  in an object of type ptrdiff_t.  Moreover, if the expres-
  sion P points either to an element of an array object or one past  the
  last  element  of  an array object, and the expression Q points to the
  last element of the same array object, the expression ((Q)+1)-(P)  has
  the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value
  zero if the expression P points one past the last element of the array
  object,  even though the expression (Q)+1 does not point to an element
  of the array object.  Unless both pointers point to  elements  of  the
  same  array  object, or one past the last element of the array object,
  the behavior is undefined.23)
  _________________________
  23) 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

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

  5.8  Shift operators                                      [expr.shift]

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

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

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

  5.9  Relational operators                                   [expr.rel]

1 The  relational  operators group left-to-right.  [Example: a<b<c means
  (a<b)<c and not (a<b)&&(b<c).  ]
  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),
  _________________________
  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.

  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 bit-
  wise exclusive function of the operands.  The operator applies only to
  integral or enumeration operands.

  5.13  Bitwise inclusive OR operator                          [expr.or]

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

  5.14  Logical AND operator                              [expr.log.and]

1 logical-and-expression:
          inclusive-or-expression
          logical-and-expression && inclusive-or-expression
  The && operator groups left-to-right.  The operands are  both  implic-
  itly  converted  to  type bool (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 ambigu-
    ous, 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  con-
    version  is  applied to the chosen operand and the converted operand
    is used in place of the original 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  func-
  tion  (_conv.func_)  type.  The subscripting operator [] and the class
  member access .  and -> operators, the & and *  unary  operators,  and
  pointer  casts (except dynamic_casts, _expr.dynamic.cast_) can be used
  in the creation of an address constant expression, but the value of an
  object  shall  not  be accessed by the use of these operators.  If the
  subscripting operator is used, one of its operands shall be  an  inte-
  gral  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_).  Function calls
  shall not be used in an address constant expression, even if the func-
  tion 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_).