______________________________________________________________________

  5   Expressions                                                 [expr]

  ______________________________________________________________________

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  5.1  Primary expressions                                   [expr.prim]

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

          id-expression:
                  unqualified-id
                  qualified-id

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

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

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
  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.
  _________________________
  2) The cast and assignment operators must still perform their specific
  conversions  as  described in _expr.cast_, _expr.static.cast_ and _ex­
  pr.ass_.

  The  parenthesized expression can be used in exactly the same contexts
  as those where the enclosed expression can be used, and with the  same
  meaning, except as otherwise indicated.

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

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

7 An identifier is  an  id-expression  provided  it  has  been  suitably
  declared   (_dcl.dcl_).    [Note:   for   operator-function-ids,   see
  _over.oper_; for  conversion-function-ids,  see  _class.conv.fct_.   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.  Call­
  ing  a  function  through an expression whose function type has a lan­
  guage linkage that is different from the language linkage of the func­
  tion   type   of   the   called  function's  definition  is  undefined
  (_dcl.link_).  For a member  function  call,  the  postfix  expression
  shall  be  an  implicit  (_class.mfct.nonstatic_,  _class.static_)  or
  explicit class member access (_expr.ref_)  whose  id-expression  is  a
  function    member    name,    or   a   pointer-to-member   expression
  (_expr.mptr.oper_) selecting a function member.  The first  expression
  in  the  postfix  expression is then called the object expression, and
  the call is as a member of the object pointed to or referred  to.   In
  the case of an implicit class member access, the implied object is the
  one pointed to by this.  [Note: a member function call of the form f()
  is  interpreted  as  (*this).f() (see _class.mfct.nonstatic_).  ] If a
  function or member function name is used, the name can  be  overloaded
  (_over_),  in  which  case  the appropriate function shall be selected
  according to the rules in _over.match_.  The function called in a mem­
  ber function call is normally selected according to the static type of
  the object expression (see _class.derived_), but if that  function  is
  virtual  the  function  actually  called  will  be the final overrider
  (_class.virtual_) of the selected function in the dynamic type of  the
  object expression [Note: the type of the object pointed or referred to
  by the current value of the object expression.   Clause  _class.cdtor_
  describes  the  behavior  of  virtual  function calls when the object-
  expression refers to an object under construction or destruction.  ]

2 The type of the function call expression is the  return  type  of  the
  statically  chosen function (i.e., ignoring the virtual keyword), even
  if the type of the function actually called is different.   This  type
  shall be a complete object type, a reference type or the type void.
  _________________________
  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.

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  (_except_) with a handler that could handle the exception, this
  handler is not considered.  ] The value of  a  function  call  is  the
  value  returned  by  the  called function except in a virtual function
  call if the return type of the final overrider is different  from  the
  return type of the statically chosen function, the value returned from
  the final overrider is converted to the return type of the  statically
  chosen function.

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

  promotions  (_conv.prom_), or a floating point type that is subject to
  the floating point promotion (_conv.fpprom_), the value of  the  argu­
  ment  is converted to the promoted type before the call.  These promo­
  tions are referred to as the default argument promotions.

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

9 Recursive calls are permitted.

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

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

1 A  simple-type-specifier  (_dcl.type_)  followed  by  a  parenthesized
  expression-list constructs a value of the  specified  type  given  the
  expression  list.   If the expression list is a single expression, the
  type conversion expression  is  equivalent  (in  definedness,  and  if
  defined   in   meaning)   to   the   corresponding   cast   expression
  (_expr.cast_).  If the simple-type-specifier specifies a  class  type,
  the  class  type  shall be complete.  If the expression list specifies
  more than a single value, the type shall be a class  with  a  suitably
  declared  constructor  (_dcl.init_,  _class.ctor_), and the expression
  T(x1, x2, ...)  is equivalent in effect to the declaration T t(x1, x2,
  ...);  for  some  invented temporary variable t, with the result being
  the value of t as an rvalue.

2 The expression T(), where T is a simple-type-specifier (_dcl.type.sim­
  ple_)  for a non-array object type or the (possibly cv-qualified) void
  type, creates an rvalue of the specified type, whose value  is  deter­
  mined  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
    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".
  _________________________
  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.

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

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

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

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

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
  (_conv.ptr_), the typeid expression throws  the  bad_typeid  exception
  (_lib.bad.typeid_).

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

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

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

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

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

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

  5.2.9  Static cast                                  [expr.static.cast]

1 The  result  of the expression static_cast<T>(v) is the result of con­
  verting the expression v to type T.  If T is  a  reference  type,  the
  result  is an lvalue; otherwise, the result is an rvalue.  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_).

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-qualifica­
  tion as, or greater cv-qualification than, cv1, and B is not a virtual
  base class of D.  The result is an lvalue of  type  cv2  D."   If  the
  lvalue of type cv1 B" is actually a sub-object of an object of type D,
  the lvalue refers to the enclosing object of type D.   Otherwise,  the
  result of the cast is undefined.  [Example:
          struct B {};
          struct D : public B {};
          D d;
          B &br = d;

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

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

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

8 An rvalue of type "pointer to cv1 B", where B is a class type, can  be
  converted  to an rvalue of type "pointer to cv2 D", where D is a class
  derived (_class.derived_) from B, if a valid standard conversion  from
  "pointer  to  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  con­
  verted  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

  conversion  from "pointer to member of B of type cv2 T" to "pointer to
  member of D of type cv2 T" exists (_conv.mem_), and cv2  is  the  same
  cv-qualification  as, or greater cv-qualification than, cv1.  The null
  member pointer value (_conv.mem_) is  converted  to  the  null  member
  pointer value of the destination type.  If class B contains 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.9) 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.
  _________________________
  9) Converting an integral constant expression (_expr.const_) with val­
  ue zero always yields a null pointer (_conv.ptr_), but converting oth­
  er expressions that happen to have value zero need not  yield  a  null
  pointer.

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

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

  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 For two pointer types T1 and T2 where

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

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

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

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

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

7 [Note:  Depending on the type of the object, a write operation through
  the pointer, lvalue  or  pointer  to  data  member  resulting  from  a
  const_cast  that casts away a const-qualifier12) may produce undefined
  behavior (_dcl.type.cv_).  ]
  _________________________
  12) const_cast is not limited to conversions that cast away  a  const-
  qualifier.

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

            X1 is T1cv1,1 * ... cv1,N *   where T1 is not a pointer type
            X2 is T2cv2,1 * ... cv2,M *   where T2 is not a pointer type
            K is min(N,M)
  casting  from X1 to X2 casts away constness if, for a non-pointer type
  T there does not exist an implicit conversion (_conv_) from:

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

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

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

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

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

12[Note: 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.13)   ]   [Note:    See
  _intro.memory_  for  the  definition of byte and _basic.types_ for the
  definition of object representation.  ]

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

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

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

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

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

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

12[Example:

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

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

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

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

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

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

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

  --If the new-initializer is omitted:

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

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

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

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

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

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

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

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

17If 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, if the type of the object being created is a
  class  type, a name lookup is performed on the name of operator delete
  using the same lookup  rules  as  those  used  to  find  operator  new
  (_class.free_).   Otherwise, a name lookup is performed on the name of
  operator delete in the scope of the  new-expression.   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 If the operand has a class type, the operand is converted to a pointer
  type by calling the above-mentioned conversion function, and the  con­
  verted  operand  is  used  in  place  of  the original operand for the
  remainder of this section.  In either alternative, if the value of the
  operand of delete is the null pointer the operation has no effect.  In
  the first alternative (delete object), the value  of  the  operand  of
  delete  shall  be  a  pointer  to a non-array object created by a new-
  expression, or a pointer to a sub-object (_intro.object_) representing
  a  base class of such an object (_class.derived_).  If not, the behav­
  ior is undefined.  In the second alternative (delete array), the value
  of the operand of delete shall be 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; it is not necessary to cast  away  the  constness
  (_expr.const.cast_) of the pointer expression before it is used as the
  operand of the delete-expression.  ]

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

4 The cast-expression in a delete-expression shall be evaluated  exactly
  once.   If the delete-expression calls the implementation deallocation
  _________________________
  14)  This  implies that an object cannot be deleted using a pointer of
  type void* because there are no objects of type void.

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

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

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

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

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

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

3 Types shall not be defined in casts.

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

5 The conversions performed by

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

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

  --a static_cast followed by a const_cast,

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

  --a reinterpret_cast followed by a const_cast,

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

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

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

  --a  pointer  to an object of derived class type, 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-defined15).

  5.7  Additive operators                                     [expr.add]

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

2 For subtraction, one of the following shall hold:

  --both operands have arithmetic or enumeration type;

  --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 or enumeration type, the usual arith­
  metic conversions are performed on them.  The result of the  binary  +
  operator is the sum of the operands.  The result of the binary - oper­
  ator 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.
  _________________________
  15) According to work underway toward the revision of ISO C, the  pre­
  ferred algorithm for integer division follows the rules defined in the
  ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is  al­
  ways rounded toward zero.

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

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

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

  5.8  Shift operators                                      [expr.shift]

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

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

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

  5.9  Relational operators                                   [expr.rel]

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

2 The  usual  arithmetic conversions are performed on operands of arith­
  metic or enumeration type.  Pointer conversions (_conv.ptr_) and qual­
  ification  conversions (_conv.qual_) are performed on pointer operands
  (or on a pointer operand and a null pointer constant) to bring them to
  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 con­
  verted 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.

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

  --Other pointer comparisons are unspecified.

  5.10  Equality operators                                     [expr.eq]

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

2 In addition, pointers to members can be compared, or a pointer to mem­
  ber  and  a  null  pointer  constant.   Pointer  to member conversions
  (_conv.mem_) and qualification conversions (_conv.qual_) are performed
  to  bring  them to 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 con­
  stant 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  func­
  tion,  the result is unspecified.  Otherwise they compare equal if and
  only if they would refer to the same member of the same  most  derived
  object  (_intro.object_)  or  the same subobject if they were derefer­
  enced with a hypothetical object of the associated class type.  [Exam­
  ple:
          struct B {
                  int f();
          };
          struct L : B { };
          struct R : B { };
          struct D : L, R { };
          int (B::*pb)() = &B::f;
          int (L::*pl)() = pb;
          int (R::*pr)() = pb;
          int (D::*pdl)() = pl;
          int (D::*pdr)() = pr;
          bool x = (pdl == pdr);    // false
   --end example]

  5.11  Bitwise AND operator                              [expr.bit.and]

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

  5.12  Bitwise exclusive OR operator                         [expr.xor]

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

  5.13  Bitwise inclusive OR operator                          [expr.or]

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

  5.14  Logical AND operator                              [expr.log.and]

1         logical-and-expression:
                  inclusive-or-expression
                  logical-and-expression && inclusive-or-expression
  The   &&   operator  groups  left-to-right.   The  operands  are  both

  implicitly converted to type bool (_conv_).  The  result  is  true  if
  both  operands  are true and false otherwise.  Unlike &, && guarantees
  left-to-right evaluation: the second operand is not evaluated  if  the
  first operand is false.

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

  5.15  Logical OR operator                                [expr.log.or]

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

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

  5.16  Conditional operator                                 [expr.cond]

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

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

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

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

3 Otherwise, if either the second or the third operand has (possibly cv-
  qualified)  class  or enumeration type, overload resolution is used to
  determine the conversions (if any)  to  be  applied  to  the  operands

  (_over.match.oper_,  _over.built_).   The  conversions thus determined
  are applied, and the converted operands are used in place of the orig­
  inal operands for the remainder of this section.

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

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

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

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

  --The second and third operands have pointer type, or one has  pointer
    type  and  the other is a null pointer constant; pointer conversions
    (_conv.ptr_) and qualification conversions  (_conv.qual_)  are  per­
    formed to bring them to a common type, whose shall be a cv-qualified
    or cv-unqualified version of the type 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 If the value being stored in an object is accessed from another object
  that  overlaps  in  any  way the storage of the first object, then the
  overlap shall be exact and the two objects shall have the  same  type,
  otherwise the behavior is undefined.

  5.18  Comma operator                                      [expr.comma]

1 The comma operator groups left-to-right.
          expression:
                  assignment-expression
                  expression , assignment-expression
  A  pair of expressions separated by a comma is evaluated left-to-right
  and the value of the left expression is discarded.  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

  member initializers (_class.static.data_), and  as  integral  non-type
  template arguments (_temp.arg_).
          constant-expression:
                  conditional-expression
  An  integral  constant-expression can involve only literals (_lex.lit­
  eral_), enumerators, const variables or static data members  of  inte­
  gral  or  enumeration  types  initialized  with  constant  expressions
  (_dcl.init_), non-type template parameters of integral or  enumeration
  types,  and  sizeof  expressions.   Floating literals (_lex.fcon_) can
  appear only if they are cast to integral or enumeration  types.   Only
  type  conversions  to  integral  or enumeration types can be used.  In
  particular, except in sizeof expressions,  functions,  class  objects,
  pointers,  or references shall not be used, and assignment, increment,
  decrement, function-call, or comma operators shall not be used.

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

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

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

  --an arithmetic constant expression,

  --an address constant expression,

  --a reference constant expression,

  --an  address  constant expression for 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 a non-type template parameter of
  pointer type, or using an expression of array (_conv.array_) or  func­
  tion  (_conv.func_)  type.  The subscripting operator [] and the class
  member access .  and -> operators, the & and *  unary  operators,  and
  pointer  casts (except dynamic_casts, _expr.dynamic.cast_) can be used
  in the creation of an address constant expression, but the value of an
  object  shall  not  be  accessed  by  the  use of these operators.  An
  expression that designates the address of a member or base class of  a

  non-POD  class  object (_class_) is not an address constant expression
  (_class.cdtor_).  Function calls shall not be used in an address  con­
  stant  expression,  even if the function is inline and has a reference
  return type.

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

6 A pointer to member constant expression shall  be  created  using  the
  unary  & operator applied to a qualified-id operand (_expr.unary.op_).