______________________________________________________________________

  5   Expressions                                       [expr]

  ______________________________________________________________________

1 [Note: this clause defines the syntax, order of evaluation, and  mean­
  ing  of  expressions.   An  expression  is a sequence of operators and
  operands that specifies a computation.  An expression can result in  a
  value and can cause side effects.

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

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

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

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

5 If during the evaluation of an expression, the result is not mathemat­
  ically  defined  or  not  in the range of representable values for its
  type, the behavior is undefined, unless such an expression is  a  con­
  stant  expression  (_expr.const_),  in  which case the program is ill-
  formed.

  +-------                 BEGIN BOX 1                -------+
  Change: The sentence above was modified to indicate  that  a  compile-
  time  diagnostic  is  required if the expression is a constant expres­
  sion; this follows a resolution adopted by ISO C to deal with a Defect
  Report.
  +-------                  END BOX 1                 -------+

  [Note:  most existing implementations of C++ ignore integer overflows.
  Treatment of division by zero and all floating point  exceptions  vary
  among machines, and is usually adjustable by a library function.  ]

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  type  cause
  conversions  and  yield result types in a similar way.  The purpose is
  to yield a common type, which is also the type of  the  result.   This
  pattern  is called the usual arithmetic conversions, which are defined
  as follows:

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

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

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

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

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

  --Otherwise, if one operand is a long int and the other unsigned  int,
  _________________________
  1) As a consequence, operands of type bool, wchar_t, or an  enumerated
  type are converted to some integral type.

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

  5.1  Primary expressions                                   [expr.prim]

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

          id-expression:
                  unqualified-id
                  qualified-id

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

3 The  keyword  this names a pointer to the object for which a nonstatic
  member function (_class.this_) is invoked.  The keyword this shall  be
  used only inside a nonstatic class member function body (_class.mfct_)
  or in a constructor mem-initializer (_class.base.init_).

4 The operator :: followed by an identifier, a qualified-id, or an oper­
  ator-function-id  is  a  primary-expression.  Its type is specified by
  the declaration of the identifier, name, or operator-function-id.  The
  result  is  the identifier, name, or operator-function-id.  The result
  is an lvalue if the identifier, name, or operator-function-id is.  The
  identifier,  name, or operator-function-id shall have global namespace
  _________________________
  2) The cast and assignment operators must still perform their specific
  conversions  as  described in _expr.cast_, _expr.static.cast_ and _ex­
  pr.ass_.

  scope.  [Note: the use of :: allows a type, an object, a function,  or
  an  enumerator declared in the global namespace to be referred to even
  if its identifier has been hidden (_basic.lookup.qual_).  ]

5 A parenthesized expression is a  primary  expression  whose  type  and
  value are identical to those of the enclosed expression.  The presence
  of parentheses does not affect whether the expression is an lvalue.

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

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

7 An  identifier  is  an  id-expression  provided  it  has been suitably
  declared   (_dcl.dcl_).    [Note:   for   operator-function-ids,   see
  _over.oper_;  for  conversion-function-ids,  see  _class.conv.fct_.  A
  class-name prefixed by ~ denotes a destructor; see _class.dtor_.  ]

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

          class-or-namespace-name:
                  class-name
                  namespace-name
  A nested-name-specifier that names a class, optionally followed by the
  keyword  template (_temp.arg.explicit_), and then followed by the name
  of a member of either that class (_class.mem_)  or  one  of  its  base
  classes  (_class.derived_),  is a qualified-id; _class.qual_ describes
  name look up for class members that appear in qualified-ids.  The type
  of the qualified-id is the type of the member.  The result is the mem­
  ber.  The result is an lvalue if the member is.  [Note: a class member
  can  be used in a qualified-id as soon as the member's point of decla­
  ration (_basic.scope.pdecl_) has been encountered in the class member-
  specification.   ] Where class-name :: class-name is used, and the two
  class-names refer to the same class, this notation names the construc­
  tor (_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 is a qualified-id;
  _namespace.qual_ describes name look up  for  namespace  members  that
  appear  in qualified-ids.  The type of the qualified-id is the type of
  the member.  The result is the member.  The result is an lvalue if the
  member is.

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

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

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

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

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

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

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

  5.2  Postfix expressions                                   [expr.post]

1 Postfix expressions group left-to-right.
          postfix-expression:
                  primary-expression
                  postfix-expression [ expression ]
                  postfix-expression ( expression-listopt )
                  simple-type-specifier ( expression-listopt )
                  postfix-expression . templateopt ::opt id-expression
                  postfix-expression -> templateopt ::opt id-expression
                  postfix-expression . pseudo-destructor-name
                  postfix-expression -> pseudo-destructor-name
                  postfix-expression ++
                  postfix-expression --
                  dynamic_cast < type-id > ( expression )
                  static_cast < type-id > ( expression )
                  reinterpret_cast < type-id > ( expression )
                  const_cast < type-id > ( expression )
                  typeid ( expression )
                  typeid ( type-id )

          expression-list:
                  assignment-expression
                  expression-list , assignment-expression
          pseudo-destructor-name:
                  ::opt nested-name-specifieropt type-name :: ~ type-name
                  ::opt nested-name-specifieropt ~ type-name

  5.2.1  Subscripting                                         [expr.sub]

1 A postfix expression followed by an expression in square brackets is a
  postfix  expression.   One  of  the  expressions  shall  have the type
  "pointer to T" and the other shall have enumeration or integral  type.
  The  result  is  an  lvalue of type "T."  The type "T" shall be a com­
  pletely-defined  object type.3) The expression E1[E2] is identical (by
  definition) to *((E1)+(E2)).  [Note: see _expr.unary_  and  _expr.add_
  for details of * and + and _dcl.array_ for details of arrays.  ]

  5.2.2  Function call                                       [expr.call]

1 There  are two kinds of function call: ordinary function call and mem­
  ber  function4)  (_class.mfct_)  call.   A  function call is a postfix
  expression followed by parentheses containing a possibly empty, comma-
  separated  list  of  expressions which constitute the arguments to the
  function.  For an ordinary function call, the postfix expression shall
  be either an lvalue that refers to a function (in which case the func­
  tion-to-pointer standard conversion (_conv.func_) is suppressed on the
  postfix expression), or it shall have pointer to function type.  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 (_over_), in which case the appro­
  priate   function   shall  be  selected  according  to  the  rules  in
  _over.match_.  The function called in a member function call  is  nor­
  mally  selected  according to the static type of the object expression
  (see _class.derived_), but if that function is  virtual  the  function
  actually  called  will be the final overrider (_class.virtual_) of the
  selected function in the dynamic type of the object expression  [Note:
  the  type of the object pointed or referred to by the current value of
  the object expression.  Clause _class.cdtor_ describes the behavior of
  virtual  function calls when the object-expression refers to an object
  under construction or destruction.  ]
  _________________________
  3) This is true even if the subscript operator is used in the  follow­
  ing common idiom: &x[0].
  4) A static member function (_class.static_) is an ordinary  function.

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

3 When  a  function  is called, each parameter (_dcl.fct_) shall be ini­
  tialized (_dcl.init_, _class.copy_, _class.ctor_) with its correspond­
  ing  argument.   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  with a handler that could handle the exception, this handler is
  not considered.  ] The value of a function call is the value  returned
  by the called function except in a virtual function call if the return
  type of the final overrider is different from the return type  of  the
  statically  chosen  function,  the value returned from the final over­
  rider is converted to the return type of the statically  chosen  func­
  tion.

4 [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 non-const reference type (_dcl.ref_).  Where
  a parameter is of reference type a temporary object is  introduced  if
  needed    (_dcl.type_,   _lex.literal_,   _lex.string_,   _dcl.array_,
  _class.temporary_).  In addition, it is possible to modify the  values
  of nonconstant objects through pointer parameters.

5 A  function  can  be  declared to accept fewer arguments (by declaring
  default arguments (_dcl.fct.default_)) or more arguments (by using the
  ellipsis,  ...   _dcl.fct_) than the number of parameters in the func­
  tion definition (_dcl.fct.def_).  ]

6 If no declaration of the called function is accessible from the  scope
  of  the  call  the  program  is ill-formed.  [Note: this implies that,
  except where the ellipsis (...)  is used, a parameter is available for
  each argument.  ]

7 When  there  is  no  parameter  for  a given argument, the argument is
  passed in such a way that the receiving function can obtain the  value
  of  the  argument  by  invoking  va_arg  (_lib.support.runtime_).  The
  lvalue-to-rvalue (_conv.lval_), array-to-pointer  (_conv.array_),  and
  function-to-pointer  (_conv.func_)  standard conversions are performed

  on the argument expression.  After these conversions, if the  argument
  does  not have arithmetic, enumeration, pointer, pointer to member, or
  class type, the program is ill-formed.  If the argument has a  non-POD
  class  type (_class_), the behavior is undefined.  If the argument has
  integral or enumeration type that is subject to  the  integral  promo­
  tions  (_conv.prom_),  or a floating point type that is subject to the
  floating point promotion (_conv.fpprom_), the value of the argument is
  converted  to the promoted type before the call.  These promotions are
  referred to as the default argument promotions.

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

9 Recursive calls are permitted.

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

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

1 A  simple-type-specifier  (_dcl.type_)  followed  by  a  parenthesized
  expression-list constructs a value of the  specified  type  given  the
  expression list.  If the expression list specifies a single value, the
  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  com­
  plete.  If the expression list specifies more than a single value, the
  type  shall  be  a  class  with  a   suitably   declared   constructor
  (_dcl.init_,  _class.ctor_),  and  the  expression  T(x1, x2, ...)  is
  equivalent in effect to the declaration T t(x1,  x2,  ...);  for  some
  invented temporary variable t, with the result being the value of t as
  an rvalue.

2 The   expression   T(),   where   T   is    a    simple-type-specifier
  (_dcl.type.simple_),  creates  an  rvalue of the specified type, whose
  value is determined by default-initialization (_dcl.init_).  [Note: if
  T  is  a  non-class  type  that is cv-qualified, the cv-qualifiers are
  ignored  when  determining  the   type   of   the   resulting   rvalue
  (_basic.lval_).  ]

  5.2.4  Pseudo destructor call                            [expr.pseudo]

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

2 The left hand side of the dot operator shall be of scalar  type.   The
  left  hand  side  of  the arrow operator shall be of pointer to scalar

  type.  This scalar type is the object type.  The  type  designated  by
  the pseudo-destructor-name shall be the same as the object type.  Fur­
  thermore, the two type-names in a pseudo-destructor-name of the form
          ::opt nested-name-specifieropt type-name :: ~ type-name
  shall designate the same scalar type.

  5.2.5  Class member access                                  [expr.ref]

1 A postfix expression followed by a dot .  or an arrow  ->,  optionally
  followed  by the keyword template (_temp.arg.explicit_), and then fol­
  lowed by an id-expression,  is  a  postfix  expression.   The  postfix
  expression  before the dot or arrow is evaluated;5) the result of that
  evaluation, together with the id-expression, determine the  result  of
  the entire postfix expression.

2 For  the  first  option  (dot)  the  type of the first expression (the
  object expression) shall be "class object" (of a complete type).   For
  the  second  option  (arrow)  the  type  of  the first expression (the
  pointer expression) shall be "pointer to class object" (of a  complete
  type).   In  these cases, the id-expression shall name a member of the
  class.  [Note: because the name of a class is inserted  in  its  class
  scope  (_class_), the name of a class is also considered a nested mem­
  ber 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  this
  subclause will address only the first  option  (dot)6).   Abbreviating
  object-expression.id-expression  as  E1.E2,  then  the type and lvalue
  properties of this expression  are  determined  as  follows.   In  the
  remainder of this subclause, cq represents either const or the absence
  of const; vq represents either volatile or the  absence  of  volatile.
  cv  represents  an  arbitrary  set  of  cv-qualifiers,  as  defined in
  _basic.type.qualifier_.

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

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

  --If E2 is a non-static data member, and the type of E1  is  "cq1  vq1
    X", and the type of E2 is "cq2 vq2 T", the expression designates the
    named member of the object designated by the first  expression.   If
  _________________________
  5) This evaluation happens even if the result is unnecessary to deter­
  mine the value of the entire postfix expression, for  example  if  the
  id-expression denotes a static member.
  6)  Note that if E1 has the type "pointer to class X", then (*(E1)) is
  an lvalue.

    E1  is  an  lvalue,  then E1.E2 is an lvalue.  Let the notation vq12
    stand for the "union" of vq1 and vq2 ; that is, if  vq1  or  vq2  is
    volatile,  then  vq12 is volatile.  Similarly, let the notation cq12
    stand for the "union" of cq1 and cq2; that is,  if  cq1  or  cq2  is
    const,  then  cq12 is const.  If E2 is declared to be a mutable mem­
    ber, then the type of E1.E2 is "vq12 T".  If E2 is not  declared  to
    be a mutable member, then the type of E1.E2 is "cq12 vq12 T".

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

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

    --Otherwise,  if  E1.E2  refers to a non-static member function, and
      the type of E2 is "function of (parameter type list) cv  returning
      T", then E1.E2 is not an lvalue.  The expression designates a non-
      static member function.  The expression can be used  only  as  the
      left-hand  operand  of a member function call (_class.mfct_).  The
      member function shall be at least as cv-qualified as E1.  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  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.

  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 can be con­
  verted to R  via  a  qualification  conversion  (_conv.qual_)  in  the
  pointer case, the result is v (converted if necessary).

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

5 If T is "pointer to cv1 B" and v has type "pointer to cv2 D" such that
  B  is  a base class of D, the result is a pointer to the unique B sub-
  object of the D object pointed to by v.  Similarly, if T is "reference
  to  cv1 B" and v has type cv2 D" such that B is a base class of D, the
  result is an lvalue for the unique7) B  sub-object  of  the  D  object
  referred  to by v.  In both the pointer and reference cases, cv1 shall
  be the same cv-qualification as,  or  greater  cv-qualification  than,
  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  like  this:  If,  in  the  most
  derived object pointed (referred) to by v, v points (refers) to a pub­
  lic 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
  _________________________
  7)  The most derived object (_intro.object_) pointed or referred to by
  v can contain other B objects as base classes, but these are  ignored.

  result is a pointer (an lvalue referring) to that  T  object.   Other­
  wise, if the type of the most derived object has an unambiguous public
  base class of type T, the result is a pointer  (reference)  to  the  T
  sub-object of the most derived object.

9 Otherwise, the run-time check fails.

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

  5.2.8  Type identification                               [expr.typeid]

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

2 When  typeid  is applied to an lvalue expression whose type is a poly­
  morphic class type (_class.virtual_), the result refers to a type_info
  object   representing   the   type   of   the   most   derived  object
  (_intro.object_) (that is, the  dynamic  type)  to  which  the  lvalue
  refers.   If the lvalue expression is obtained by applying the unary *
  operator  to  a  pointer8)  and  the  pointer  is a null pointer value
  _________________________
  8) If p is an expression of pointer type, then *p, (*p), *(p), ((*p)),

  (_conv.ptr_), the typeid expression throws  the  bad_typeid  exception
  (_lib.bad.typeid_).

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

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

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 result of a typeid expression is an lvalue that has
  the  incompletely-defined  class type const std::type_info, and a pro­
  gram that explicitly names this class type  before  inclusion  of  the
  header is ill-formed.

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

  5.2.9  Static cast                                  [expr.static.cast]

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

  _________________________
  *((p)), and so on all meet this requirement.

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

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

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

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

7 A value of integral type can be explicitly converted to an enumeration
  type.   The  value  is  unchanged  if the integral value is within the
  range of the enumeration values (_dcl.enum_). Otherwise, the resulting
  enumeration value is unspecified.

8 An  rvalue of type "pointer to cv1 B", where B is a class type, can be
  converted to an rvalue of type "pointer to cv2 D", where D is a  class
  derived  (_class.derived_) from B, if a valid standard conversion from
  "pointer to cv2 D" to "pointer to cv2 B" exists (_conv.ptr_),  cv2  is
  the  same  cv-qualification as, or greater cv-qualification than, cv1,
  and B is not a virtual base class of D and not a base class of a  vir­
  tual  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 not a virtual base class (_class.derived_) of D and  not  a
  base  class  of a virtual base class of D, if a valid standard conver­
  sion from "pointer to member of B of type cv2 T" to "pointer to member
  of  D  of  type  cv2  T"  exists (_conv.mem_), and cv2 is the same cv-
  qualification as, or greater cv-qualification  than,  cv1.   The  null
  member  pointer  value  (_conv.mem_)  is  converted to the null member
  pointer value of the destination type.  If class B contains the origi­
  nal  member, or is a base or derived class of the class containing the
  original member, the resulting pointer to member points to the  origi­
  nal  member.   Otherwise, the result of the cast is undefined.  [Note:
  although class B need not contain the  original  member,  the  dynamic
  type of the object on which the pointer to member is dereferenced must
  contain the original member; see _expr.mptr.oper_.  ]

  5.2.10  Reinterpret cast                       [expr.reinterpret.cast]

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

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

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

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

5 A value of integral type or enumeration type can  be  explicitly  con­
  verted  to a pointer.  A pointer converted to an integer of sufficient
  size (if any such exists on the implementation) and back to  the  same
  pointer  type  will have its original value; mappings between pointers
  and integers are otherwise implementation-defined.

6 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.9) 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.10) The
  null member pointer value (_conv.mem_) is converted to the null member
  pointer  value of the destination type.  The result of this conversion
  is unspecified, except in the following cases:

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

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

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

11An  lvalue expression of type T1 can be cast to the type "reference to
  T2" if an expression  of  type  "pointer  to  T1"  can  be  explicitly
  _________________________
  9)  The types may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.
  10) T1 and T2 may have different cv-qualifiers, subject to the overall
  restriction that a reinterpret_cast cannot cast away constness.

  converted  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 *
  operators.  The result is an lvalue that refers to the same object  as
  the  source  lvalue,  but with a different type.  No temporary is cre­
  ated, no copy is made, and constructors (_class.ctor_)  or  conversion
  functions (_class.conv_) are not called.

  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 Any expression may be cast to its own type using a  const_cast  opera­
  tor.

3 An  rvalue  of  type "pointer to cv1 T" can be explicitly converted to
  the type "pointer to cv2 T", where T is any object type  or  the  void
  type  and,  where  cv1  and  cv2 are cv-qualifications, using the cast
  const_cast<cv2 T*>.  An lvalue of type cv1 T can  be  explicitly  con­
  verted  to  an  lvalue  of  type cv2 T, where T is any object type and
  where cv1 and cv2 are cv-qualifications, using the cast const_cast<cv2
  T&>.   The  result  of a pointer or reference const_cast refers to the
  original object.

4 An rvalue of type "pointer to member of  X  of  type  cv1  T"  can  be
  explicitly  converted  to the type "pointer to member of X of type cv2
  T", where T is a data member type  and  where  cv1  and  cv2  are  cv-
  qualifiers,  using  the  cast const_cast<cv2 T X::*>.  The result of a
  pointer to member const_cast will refer to  the  same  member  as  the
  original (uncast) pointer to data member.

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

6 [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-qualifier11) may produce  undefined
  behavior (_dcl.type.cv_).  ]

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

7 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 (_conv_) from:

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

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

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

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

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

11[Note: these rules are not intended to protect constness in all cases.
  For instance, conversions between pointers to functions are  not  cov­
  ered  because  such  conversions lead to values whose use causes unde­
  fined behavior.  For the same reasons, conversions between pointers to
  member  functions, and in particular, the conversion from a pointer to
  a const member function to a pointer to a non-const  member  function,
  are not covered.  ]

  5.3  Unary expressions                                    [expr.unary]

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

  5.3.1  Unary operators                                 [expr.unary.op]

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

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

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

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

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

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

  The type of the result is the type of the promoted operand.

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

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

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

  5.3.2  Increment and decrement                         [expr.pre.incr]

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

2 The  operand  of prefix -- is modified by substracting 1.  The operand
  shall not be of type bool.  The requirements on the operand of  prefix
  -- and the properties of its result are otherwise the same as those of
  prefix ++.

  5.3.3  Sizeof                                            [expr.sizeof]

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

  _________________________
  12) sizeof(bool) is not required to be 1.

2 When  applied to a reference, the result is the size of the referenced
  type.  When applied to a class, the result is the number of  bytes  in
  an  object  of  that  class including any padding required for placing
  objects of that type in an array.  The size of a  most  derived  class
  shall  be  greater  than  zero  (_intro.object_).   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 an implementation-defined type which is
  the same type as that which is named size_t  in  the  standard  header
  <cstddef>(_lib.support.types_).

  5.3.4  New                                                  [expr.new]

1 The  new-expression  attempts  to  create  an  object  of  the type-id
  (_dcl.name_) to which it is applied.  This type shall  be  a  complete
  nonabstract  object type or array type (_intro.object_, _basic.types_,
  _class.abstract_).  [Note: because, references are not objects, refer­
  ences  cannot be created by new-expressions.  ] [Note: the type-id may
  be a cv-qualified type, in which case the object created by  the  new-
  expression has a cv-qualified type.  ]
          new-expression:
                  ::opt new new-placementopt new-type-id new-initializeropt
                  ::opt new new-placementopt ( type-id ) new-initializeropt
          new-placement:
                  ( expression-list )
          new-type-id:
                  type-specifier-seq new-declaratoropt
          new-declarator:
                  ptr-operator new-declaratoropt
                  direct-new-declarator
          direct-new-declarator:
                  [ expression ]
                  direct-new-declarator [ constant-expression ]
          new-initializer:
                  ( expression-listopt )
  Entities  created  by  a  new-expression have dynamic storage duration
  (_basic.stc.dynamic_).  [Note: the lifetime of such an entity  is  not
  necessarily  restricted to the scope in which it is created.  ] If the
  entity is an object, the  new-expression  returns  a  pointer  to  the
  object  created.   If  it  is  an  array, the new-expression returns a
  pointer to the initial element of the array.

2 The new-type-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 Parentheses shall not appear in the new-type-id of a new-expression.

4 [Example:
          new int(*[10])();       // error
  is ill-formed because the binding is
          (new int) (*[10])();    // error
  Instead, the explicitly parenthesized version of the new operator  can
  be used to create objects of compound types (_basic.compound_):
          new (int (*[10])());
  allocates an array of 10 pointers to functions (taking no argument and
  returning int).  ]

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

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

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

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

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

10An  implementation  shall  provide  default definitions for the global
  allocation    functions    operator new()    for    non-array    types

  (_basic.stc.dynamic_,  _lib.new.delete.single_)  and  operator new[]()
  for array types (_lib.new.delete.array_).  [Note: A  C++  program  can
  provide     alternative     definitions     of     these     functions
  (_lib.replacement.functions_),    and/or    class-specific    versions
  (_class.free_).   ]  When  the keyword new in a new-expression is pre­
  ceeded by the unary :: operator, the  global  allocation  function  is
  used to allocate the storage.

11The  new-placement syntax 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 correspoding types of the expressions in
  the new-placement.

12[Example:

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

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

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

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

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

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

14If the type of the object created by the new-expression is T:

  --If the new-initializer is omitted and T  is  a  non-POD  class  type
    (_class_)  (or array thereof), then if the default constructor for T
    is accessible it is called, otherwise the program is ill-formed;

  --If the new-initializer is omitted and T is a  const-qualified  type,
    if  T  is a class type with an explicitly-declared default construc­
    tor, the default constructor for T is  called,  otherwise  the  new-
    expression is ill-formed;

  --If   the   new-initializer   is   omitted   and  T  is  a  POD  type
    (_basic.types_), then the  object  thus  created  has  indeterminate
    value;

  --If  the  new-initializer  is  of the form (), default-initialization
    shall be performed (_dcl.init_);

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

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

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

15Access and ambiguity control are done for the allocation function, the
  deallocation    function    (_class.free_)    and    the   constructor
  (_class.ctor_).

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

17If the constructor exits using an  exception  and  the  new-expression
  does  not  contain  a  new-placement,  then  the deallocation function
  (_basic.stc.dynamic.deallocation_, _class.free_) is called to free the
  memory  in  which  the  object  was being constructed, after which the
  exception continues to propagate in the context of the new-expression.

18If  the  constructor  exits  using an exception and the new-expression
  contains a new-placement, a name lookup is performed on  the  name  of
  operator  delete  in  the scope of this new-expression.  If the lookup
  succeeds and exactly one of the declarations found matches the  decla­
  ration  of  that  placement  operator new, then the matching placement
  operator delete shall be called (_basic.stc.dynamic.deallocation_).

19A declaration of placement operator delete matches the declaration  of
  a placement operator new when it has the same number of parameters and
  all parameter types except the first are identical  disregarding  top-
  level cv-qualifiers.

20If  placement  operator  delete is called, it is passed the same argu­
  ments as were passed to placement operator new.  If the implementation
  is  allowed to make a copy of an argument as part of the placement new
  call, it is allowed to make a copy (of the  same  original  value)  as
  part  of  the placement delete call, or to reuse the copy made as part
  of the placement new call.  If the copy is elided  in  one  place,  it
  need not be elided in the other.

21The  way the object was allocated determines how it is freed: if it is
  allocated by ::new, then it is freed by ::delete,  and  if  it  is  an
  array, it is freed by delete[] or ::delete[] as appropriate.

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

  5.3.5  Delete                                            [expr.delete]

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

2 In either alternative, if the value of the operand of  delete  is  the
  null  pointer  the operation has no effect.  Otherwise, if the operand
  has a class type, the operand is converted to a pointer type by  call­
  ing the above-mentioned conversion function, and the converted operand
  is used in place of the original operand for  the  remainder  of  this
  section.   In  the first alternative (delete object), the value of the
  operand of delete shall be a pointer to a non-array object created  by
  a new-expression, or a pointer to a sub-object (_intro.object_) repre­
  senting a base class of such an object (_class.derived_).  If not, the
  behavior  is undefined.  In the second alternative (delete array), the
  value of the operand of delete shall be a pointer to the first element
  of  an  array  created  by  a new-expression.  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.  ]

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

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 and
  render the pointer invalid.  [Note: the value of a pointer that refers
  to deallocated storage is indeterminate.  ]

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

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 construction; see _class.base.init_).

7 To free the storage pointed to,  the  delete-expression  will  call  a
  deallocation function (_basic.stc.dynamic.deallocation_).

8 An implementation provides default definitions of the global dealloca­
  tion      functions       operator delete()       for       non-arrays
  (_lib.new.delete.single_)    and    operator delete[]()   for   arrays
  (_lib.new.delete.array_).  A C++ program can provide alternative defi­
  nitions   of  these  functions  (_lib.replacement.functions_),  and/or
  class-specific versions (_class.free_).  When the keyword delete in  a
  delete-expression  is  preceeded  by the unary :: operator, the global
  deallocation function is used to deallocate the storage.

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

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

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

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

3 Types shall not be defined in casts.

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

5 The conversions performed by static_cast  (_expr.static.cast_),  rein­
  terpret_cast           (_expr.reinterpret.cast_),           const_cast
  (_expr.const.cast_), or any sequence thereof, can be  performed  using
  the  cast  notation  of  explicit  type conversion.  The same semantic
  restrictions and behaviors apply.  If a given conversion can be inter­
  preted as a static_cast or reinterpret_cast, the static_cast interpre­
  tation is used  even  if  the  resulting  static_cast  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 the static_cast or rein­
  terpret_cast interpretation is used is unspecified.

7 In addition to those conversions, the following static_cast and  rein­
  terpret_cast  operations  may  be performed using the cast notation of
  explicit type conversion, even if the base class type is not  accessi­
  ble:

  --a  pointer  to an object of derived class type, an lvalue of derived
    class type, or a pointer to member of  derived  class  type  may  be
    explicitly  converted to a pointer to a base class type, a reference
    to a base class type, or a pointer to member of a base  class  type,
    respectively;

  --a  pointer  to an object of base class type, an lvalue of base class
    type, or a pointer to member of base class type  may  be  explicitly
    converted  to  a  pointer  to a derived class type, a reference to a
    derived class type, 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" to its first operand, which shall be  of
  class T or of a class of which T is an unambiguous and accessible base
  class.  The result is an object or a function of the type specified by
  the second operand.

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

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

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

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

  5.6  Multiplicative operators                               [expr.mul]

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

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

3 The binary * operator indicates multiplication.

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

  5.7  Additive operators                                     [expr.add]

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

2 For subtraction, one of the following shall hold:

  --both operands have arithmetic or enumeration type;

  --both operands are pointers to cv-qualified  or  cv-unqualified  ver­
    sions of the same completely defined object type; or

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

3 If both operands have arithmetic type, the  usual  arithmetic  conver­
  sions  are  performed on them.  The result of the binary + operator is
  the sum of the operands.  The result of the binary - operator  is  the
  difference  resulting  from the subtraction of the second operand from
  the first.

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

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

  object  and  the result points to an element of the same array object,
  or the pointer operand points to the  element  of  an  array  and  the
  result points one past the last element of the same array.

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

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
  _________________________
  14) Another way to approach pointer arithmetic is first to convert the
  pointer(s) to character pointer(s): In this scheme the integral  value
  of the expression added to or subtracted from the converted pointer is
  first multiplied by the size of the object originally pointed to,  and
  the  resulting  pointer  is  converted back to the original type.  For
  pointer subtraction, the result of the difference between the  charac­
  ter pointers is similarly divided by the size of the object originally
  pointed to.

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

  The operands shall be of integral or  enumeration  type  and  integral
  promotions  are performed.  The type of the result is that of the pro­
  moted left operand.  The behavior is undefined if the right operand is
  negative,  or  greater than or equal to the length in bits of the pro­
  moted left operand.

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

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

  5.9  Relational operators                                   [expr.rel]

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

2 The usual arithmetic conversions are performed on operands  of  arith­
  metic  or  enumeration  type.   Pointer  conversions  are performed on
  pointer operands to bring them to the same type, which shall be a  cv-
  qualified  or  cv-unqualified  version  of  the  type  of  one  of the
  operands.  [Note: this implies that any pointer can be compared  to  a
  null pointer constant and that any object pointer can be compared to a
  pointer of cv-qualified or cv-unqualified type void*  (in  the  latter
  case  the pointer is first implicitly converted to void*).  ] Pointers
  to objects or functions of the same type (after  pointer  conversions)
  can be compared, 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
    or  functions, or only one of them is null, the results of p<q, p>q,
    p<=q, and p>=q are unspecified.

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

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

  +-------                      BEGIN BOX 2                     -------+
  Should  it at least be required to be consistent across all objects of
  the same type within the execution of a single program?
  +-------                       END BOX 2                      -------+

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

  --Other pointer comparisons are unspecified.

  5.10  Equality operators                                     [expr.eq]

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

2 In addition, pointers to members can be compared.  Pointer  to  member
  conversions (_conv.mem_) are performed to bring them to the same type,
  which shall be a cv-qualified or cv-unqualified version of the type of
  one  of  the operands.  [Note: this implies that any pointer to member
  can be compared to an integral constant expression evaluating to zero.
  ]  If  both  operands are null, they compare equal.  Otherwise if only
  one is null, they compare unequal.  Otherwise if either is  a  pointer
  to  a  virtual  member function, the result is unspecified.  Otherwise
  they compare equal if and only if they would refer to the same  member
  of the same most derived object (_intro.object_) or the same subobject
  if they were dereferenced with a hypothetical object of the associated
  class type.  [Example:

          struct B {
                  int f();
          };
          struct L : B { };
          struct R : B { };
          struct D : L, R { };
          int (B::*pb)() = &B::f;
          int (L::*pl)() = pb;
          int (R::*pr)() = pb;
          int (D::*pdl)() = pl;
          int (D::*pdr)() = pr;
          bool x = (pdl == pdr);    // false
   --end example]

  5.11  Bitwise AND operator                              [expr.bit.and]

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

  5.12  Bitwise exclusive OR operator                         [expr.xor]

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

  5.13  Bitwise inclusive OR operator                          [expr.or]

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

  5.14  Logical AND operator                              [expr.log.and]

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

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

  5.15  Logical OR operator                                [expr.log.or]

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

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

  5.16  Conditional operator                                 [expr.cond]

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

2 If either the second or the  third  operand  has  type  (possibly  cv-
  qualified)  void,  then  the 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, and one of
  the following shall hold:

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

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

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

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

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

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

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

  --The second and third operands have pointer type, or one has  pointer
    type  and  the other is a null pointer constant; pointer conversions
    (_conv.ptr_) and qualification conversions  (_conv.qual_)  are  per­
    formed  to bring them to 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.

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

  5.17  Assignment operators                                  [expr.ass]

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

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

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

4 If the left operand is of class type, the  class  shall  be  complete.
  Assignment  to  objects of a class (_class_) X is defined by the func­
  tion X::operator=() (_over.ass_).  Unless X::operator=() is explicitly
  declared  in  the  class member-specification, the implicitly-declared

  default assignment operator is  used  for  assignment  (_class.copy_).
  This  implies  that  an  object of a class derived from X (directly or
  indirectly) by unambiguous public derivation (_class.derived_) can  be
  assigned to an X.

5 For  class  objects, assignment is not in general the same as initial­
  ization (_dcl.init_, _class.ctor_, _class.init_, _class.copy_).

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

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

8 See _except.throw_ for throw expressions.

  5.18  Comma operator                                      [expr.comma]

1 The comma operator groups left-to-right.
          expression:
                  assignment-expression
                  expression , assignment-expression
  A pair of expressions separated by a comma is evaluated  left-to-right
  and  the  value of the left expression is discarded.  All side effects
  (_intro.execution_) of the left expression, except for the destruction
  of  temporaries  (_class.temporary_), are performed before the evalua­
  tion of the right expression.  The type and value of  the  result  are
  the  type  and  value of the right operand; the result is an lvalue if
  its right operand is.

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

  5.19  Constant expressions                                [expr.const]

1 In  several places, C++ requires expressions that evaluate to an inte­
  gral  or  enumeration  constant:   as   array   bounds   (_dcl.array_,
  _expr.new_), as case expressions (_stmt.switch_), as bit-field lengths
  (_class.bit_), as enumerator initializers (_dcl.enum_), as static mem­
  ber  initializers (_class.static.data_), and as integral non-type tem­
  plate arguments (_temp.arg_).
          constant-expression:
                  conditional-expression
  An   integral   constant-expression   can   involve   only    literals
  (_lex.literal_),  enumerators,  const variables or static data members

  of integral or enumeration types initialized with constant expressions
  (_dcl.init_),  and sizeof expressions.  Floating literals (_lex.fcon_)
  can appear only if they are cast to  integral  or  enumeration  types.
  Only  type  conversions  to integral or enumeration types can be used.
  In particular, except in sizeof expressions, functions, class objects,
  pointers,  or references shall not be used, and assignment, increment,
  decrement, function-call, or comma operators shall not be used.

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

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

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

  --an arithmetic constant expression,

  --an address constant expression,

  --a reference constant expression,

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

  --a pointer to member constant expression.

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

4 An address constant expression is a pointer to an  lvalue  designating
  an object of static storage duration, a string literal (_lex.string_),
  or a function.  The pointer shall be  created  explicitly,  using  the
  unary   &  operator,  or  implicitly  using  an  expression  of  array
  (_conv.array_) or function (_conv.func_) type.  The subscripting oper­
  ator  []  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 con­
  stant expression, but the value of an object shall not be accessed  by
  the use of these operators.  An expression that designates the address
  of a member or base class of a non-POD class object (_class_)  is  not
  an  address constant expression (_class.cdtor_).  Function calls shall
  not be used in an address constant expression, even if the function is
  inline and has a reference return type.

5 A  reference constant expression is an lvalue designating an object of
  static storage duration or a function.  The subscripting operator  [],

  the  class member access .  and -> operators, the & and * unary opera­
  tors, and reference casts (except those invoking user-defined  conver­
  sion    functions    (_class.conv.fct_)   and   except   dynamic_casts
  (_expr.dynamic.cast_)) can be used in the creation of a reference con­
  stant  expression, but the value of an object shall not be accessed by
  the use of these operators An lvalue expression that designates a mem­
  ber  or base class of a non-POD class object (_class_) is not a refer­
  ence 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_).