______________________________________________________________________

  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_).  Uses of overloaded operators are
  transformed  into  function  calls as described in _over.oper_.  Over­
  loaded 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  guaranteed  for  operands  of  type  bool.
  [Example: the left operand of += must not have type bool.  ] ]

3 This clause defines the 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  the  language  itself.   However,
  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.  [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.  ]

  +-------                 BEGIN BOX 1                -------+
  ISO  C  recently dealt with a Defect Report which asked whether a com­
  pile-time diagnostic was permissible  in  cases  where  the  undefined
  behavior would occur in evaluating a compile-time constant expression.
  WG14 decided that it was permissible -  we  probably  need  equivalent
  wording here.
  +-------                  END BOX 1                 -------+

6 Except  where  noted,  operands  of  types  const T,  volatile T,  T&,
  const T&, and volatile T& can be used as if they  were  of  the  plain
  type  T.  Similarly, except where noted, operands of type T* const and
  T* volatile can be used as if they were of the plain type  T*.   Simi­
  larly,  a  plain  T  can  be  used  where a volatile T or a const T is
  required.  These rules apply in  combination  so  that,  except  where
  noted, a T* const volatile can be used where a T* is required.

7 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.  [Note: a reference can be
  thought of as a name of an object.  ]

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

9 User-defined conversions of class types to and from fundamental types,
  pointers, and so on, can be defined  (_class.conv_).   If  unambiguous
  (_over.match_),  such  conversions are applied wherever a class object
  appears as an operand  of  an  operator  or  as  a  function  argument
  (_expr.call_).

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

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

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

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

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

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

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

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

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

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

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

12The  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
  _________________________
  1)  As a consequence, operands of type bool, wchar_t, or an enumerated
  type are converted to some integral type.
  2) The cast and assignment operators must still perform their specific
  conversions as described in _expr.cast_, _expr.static.cast_  and  _ex­
  pr.ass_.

  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 be of 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.

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

  +-------                 BEGIN BOX 2                -------+
  Issue: now it's allowed to  invoke  ~int(),  but  ~class-name  doesn't
  allow for that.
  +-------                  END BOX 2                 -------+

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  (_dcl.type_)  followed  by
  ::, 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  member.   The  result  is  an
  lvalue  if the member is.  Where class-name :: class-name is used, and
  the two class-names refer to the same class, this notation  names  the
  constructor (_class.ctor_).  Where class-name :: ~ class-name is used,
  the two class-names shall refer to the same class; this notation names
  the destructor (_class.dtor_).

9 A  nested-name-specifier  that  names  a namespace (_basic.namespace_)
  followed by ::, 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 ++
                  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

  5.2.1  Subscripting                                         [expr.sub]

1 A postfix expression followed by an expression in square brackets is a
  postfix expression.  [Note: the intuitive meaning is that  of  a  sub­
  script.   ]  One of the expressions shall have the type "pointer to T"
  and the other shall be of enumeration or integral type.  The result is
  an  lvalue  of  type  "T."  The type "T" shall be a completely-defined
  object type.  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 function3) (_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 ordinary function call, the postfix expression shall be
  an lvalue that refers to a function; the function-to-pointer  standard
  conversion  (_conv.func_) is suppressed on the postfix expression of a
  function call.  For 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 mem­
  ber function name is used, the name can  be  overloaded  (_over_),  in
  _________________________
  3)  A static member function (_class.static_) is an ordinary function.

  which case the appropriate function shall be selected according to the
  rules in _over.match_.  The function called in a member function  call
  is  normally  selected  according  to  the  static  type of the object
  expression (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 When  a  function  is called, each parameter (_dcl.fct_) shall be ini­
  tialized (_dcl.init_, _class.copy_, _class.ctor_) with its correspond­
  ing  argument.  During the initialization of a parameter, an implemen­
  tation may avoid the construction of extra  temporaries  by  combining
  the  conversions on the associated argument and/or the construction 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 a the point of call in the calling function.
  ] 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 con­
  verted to the return type of the statically chosen function.

4 [Note: a function can change the values of its nonconstant parameters,
  but  these  changes  cannot  affect the values of the arguments except
  where a parameter is of a non-const reference type (_dcl.ref_).  Where
  a  parameter  is of reference type a temporary object is introduced if
  needed   (_dcl.type_,   _lex.literal_,   _lex.string_,    _dcl.array_,
  _class.temporary_).   In addition, it is possible to modify the values
  of nonconstant objects through pointer parameters.

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

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

7 When there is no parameter for  a  given  argument,  the  argument  is
  passed  in such a way that the receiving function can obtain the value
  of the  argument  by  invoking  va_arg  (_lib.support.runtime_).   The

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

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

9 Recursive calls are permitted.

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

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

1 A  simple-type-specifier  (_dcl.type_)  followed  by  a  parenthesized
  expression-list  constructs  a  value  of the specified type given the
  expression list.  If the expression list specifies a single value, the
  expression  is  equivalent (in definedness, and if defined in meaning)
  to the corresponding cast expression (_expr.cast_).  If the 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 declara­
  tion T t(x1, x2, ...); for some invented temporary  variable  t,  with
  the result being the value of t as an rvalue.

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

  5.2.4  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;4) the result of that
  _________________________
  4) 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.

  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).   The  id-expression  shall name a member of that class, except
  that an imputed destructor can be explicitly invoked for a scalar type
  (_class.dtor_).   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)5).

3 If  the  id-expression is a qualified-id, the nested-name-specifier of
  the qualified-id can specify a namespace name or a class name.  If the
  nested-name-specifier  of the qualified-id specifies a namespace name,
  the name is looked up in the context  in  which  the  entire  postfix-
  expression  occurs.   If the nested-name-specifier of the qualified-id
  specifies a class name, the class name is looked up as a type both  in
  the  class  of  the  object expression (or the class pointed to by the
  pointer expression) and the  context  in  which  the  entire  postfix-
  expression  occurs.  [Note: because the name of a class is inserted in
  its class scope (_class_), the name of a class is  also  considered  a
  nested  member  of  that class.  ] These searches shall yield a single
  type.  [Note: the type might be found in either or both  contexts.   ]
  If    the   nested-name-specifier   contains   a   class   template-id
  (_temp.names_), its template-arguments are evaluated in the context in
  which the entire postfix-expression occurs.

4 Similarly,  if the id-expression is a conversion-function-id, its con­
  version-type-id shall denote the same type  in  both  the  context  in
  which  the  entire postfix-expression occurs and in the context of the
  class of the object expression (or the class pointed to by the pointer
  expression).

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

6 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
  _________________________
  5) Note that if E1 has the type "pointer to class X", then (*(E1))  is
  an lvalue.

    class.  The type of E1.E2 is T.

  --If E2 is a (possibly overloaded) 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".

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

  --If E2 is a (possibly overloaded) 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 member
    function (of some class X).  The expression can be used only as  the
    left-hand  operand  of  a  member function call (_class.mfct_).  The
    member function shall be at least as cv-qualified as E1.   The  type
    of E1.E2 is "function of (parameter type list) cv returning T".

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

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

  +-------                 BEGIN BOX 3                -------+
  This does not cover the case where E2 is the overloaded name of a mem­
  ber function that includes both static and non-static versions.
  +-------                  END BOX 3                 -------+

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

  5.2.5  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 type of the result is the same as the type of
  the operand, but it  is  not  an  lvalue.   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.6  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 unique6) 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
  _________________________
  6) The most derived object (_intro.object_) pointed or referred to  by
  v  can contain other B objects as base classes, but these are ignored.

  converted 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.  Otherwise, the run-time  check
  fails.

9 The  value  of a failed cast to pointer type is the null pointer value
  of the required result type.  A failed cast to reference  type  throws
  bad_cast (_lib.bad.cast_).  [Example:
          class A { virtual void f(); };
          class B { virtual void g(); };
          class D : public virtual A, private B {};
          void g()
          {
              D   d;
              B*  bp = (B*)&d;  // cast needed to break protection
              A*  ap = &d;      // public derivation, no cast needed
              D&  dr = dynamic_cast<D&>(*bp);  // 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;                    // okay: finds unique A
              D*  dp  = dynamic_cast<D*>(ap);  // fails: ambiguous
              E*  ep  = (E*)ap;                // error: 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.7  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  pointer7)  and  the  pointer  is a null pointer value
  (_conv.ptr_), the typeid expression throws  the  bad_typeid  exception
  (_lib.bad.typeid_).

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

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

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

6 If  the header <typeinfo> (_lib.type.info_) is not included prior to a
  use of typeid, the result of a typeid expression is an lvalue that has
  the  incompletely-defined  class type const std::type_info, and a pro­
  gram that explicitly names this class type  before  inclusion  of  the
  header is ill-formed.

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

  5.2.8  Static cast                                  [expr.static.cast]

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

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

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

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

4 Any expression can be explicitly converted  to  type  cv  void."   The
  expression value is discarded.

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

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

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

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

8 An  rvalue of type "pointer to cv1 B", where B is a class type, can be
  converted to an rvalue of type "pointer to cv2 D", where D is a  class
  derived  (_class.derived_) from B, if a valid standard conversion from
  "pointer to cv2 D" to "pointer to cv2 B" exists (_conv.ptr_),  cv2  is
  the  same  cv-qualification as, or greater cv-qualification than, cv1,
  and B is not a virtual base  class  of  D.   The  null  pointer  value
  (_conv.ptr_) is converted to the null pointer value of the destination
  type.  If the rvalue of type "pointer to cv1 B" points to a B that  is

  actually  a  sub-object  of an object of type D, the resulting pointer
  points to the enclosing object of type D.  Otherwise,  the  result  of
  the cast is undefined.

9 An  rvalue  of type "pointer to member of D of type cv1 T" can be con­
  verted to an rvalue of type "pointer to member of B of  type  cv2  T",
  where  B is a nonvirtual base class (_class.derived_) 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
  original member, or is a base or derived class of the class containing
  the original member, the resulting pointer to  member  points  to  the
  original  member.   Otherwise,  the  result  of the cast is undefined.
  [Note: although class B need not  contain  the  original  member,  the
  dynamic  type of the object on which the pointer to member is derefer­
  enced must contain the original member; see _expr.mptr.oper_.  ]

  5.2.9  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.  Types  shall
  not  be  defined  in a reinterpret_cast.  Conversions that can be per­
  formed explicitly using reinterpret_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''.  ]

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 can be explicitly converted to a pointer.   A
  pointer converted to an integer of sufficient size (if any such exists
  on the implementation) and back to the same pointer type will have its
  original  value;  mappings between pointers and integers are otherwise
  implementation-defined.

6 The operand of a pointer cast can be an rvalue  of  type  "pointer  to
  incomplete class type".  The destination type of a pointer cast can be
  "pointer to incomplete class type".  In such cases, if  there  is  any
  inheritance  relationship  between the source and destination classes,
  the behavior is undefined.

7 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 differs from the
  type used in the definition of the function is undefined.  Except that
  converting an rvalue of type "pointer to T1" to the type  "pointer  to
  T2" (where T1 and T2 are function types) and back to its original type
  yields the original pointer value, the result of such a  pointer  con­
  version  is  unspecified.  [Note: see also _conv.ptr_ for more details
  of pointer conversions.  ]

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

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

10An 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.9) 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.

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

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

  converted  to the type "pointer to T2" using a reinterpret_cast.  That
  is, a reference cast reinterpret_cast<T&>(x) has the  same  effect  as
  the  conversion  *reinterpret_cast<T*>(&x)  with  the built-in & and *
  operators.  The result is an lvalue that refers to the same object  as
  the  source  lvalue,  but with a different type.  No temporary is cre­
  ated, no copy is made, and constructors (_class.ctor_)  or  conversion
  functions (_class.conv_) are not called.

  5.2.10  Const cast                                   [expr.const.cast]

1 The  result  of  the  expression const_cast<T>(v) is of type T.  Types
  shall not be defined in a const_cast.  Conversions that  can  be  per­
  formed explicitly using const_cast are listed below.  No other conver­
  sion shall be performed explicitly using const_cast.

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

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

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

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

6 The  following rules define casting away constness.  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  (e.g.,  int),  there does not exist an implicit conversion (_conv_)
  _________________________
  10) const_cast is not limited to conversions that cast away  a  const-
  qualifier.

  from:

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

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

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

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

9 [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.  For multi-level pointers to data members, or multi-
  level mixed object and member pointers, the same rules  apply  as  for
  multi-level  object  pointers.   That is, the "member of" attribute is
  ignored for purposes of determining whether const has been cast  away.
  ]

  5.3  Unary expressions                                    [expr.unary]

1 Expressions with unary operators group right-to-left.
          unary-expression:
                  postfix-expression
                  ++  unary-expression
                  --  unary-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  means  indirection: the expression 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 expression 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.  [Example: the address
  of  an  object of type "const int" has type "pointer to const int."  ]
  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 non­
  static 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]

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

  +-------                      BEGIN BOX 4                     -------+
  This section probably needs to take into account const and  its  rela­
  tionship to mutable.
  +-------                       END BOX 4                      -------+

4 The  address  of an object of incomplete type can be taken, but if the
  complete type of that object has the address-of operator (operator&())
  overloaded,  then  the  behavior  is  undefined  (and no diagnostic is
  required).  The operand of & shall not be a bit-field.

5 The address of an overloaded function (_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.

  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 decremented analogously to the  prefix  ++
  operator, except that the operand shall not be of type bool.

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

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
  such  objects  in  an array.  The size of any class or class object is
  greater than zero.  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.
  _________________________
  11) sizeof(bool) is not required to be 1.

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

5 Types shall not be defined in a sizeof expression.

6 The  result  is  a constant of an implementation-defined type which is
  the same type as that which is named size_t  in  the  standard  header
  <cstddef>(_lib.support.types_).

  5.3.4  New                                                  [expr.new]

1 The  new-expression  attempts  to  create  an  object  of  the type-id
  (_dcl.name_) to which it is applied.  This type shall  be  a  complete
  nonabstract  object type or array type (_intro.object_, _basic.types_,
  _class.abstract_).  [Note: because, references are not objects, refer­
  ences cannot be created by new-expressions.  ]
          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 in a new-expression is the longest possible  sequence  of
  new-declarators.   This prevents ambiguities between declarator opera­
  tors &, *, [], and their expression counterparts.  [Example:
          new int*i;     // syntax error: parsed as `(new int*) i'
                         //               not as `(new int)*i'
  The * is the pointer declarator and not the  multiplication  operator.
  ]

3 Parentheses  shall not appear in a new-type-id used as the operand for
  new.

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]
  return an 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_)  with  a  strictly  positive
  value.  The expression in a direct-new-declarator shall be of integral
  type (_basic.fundamental_) with a non-negative value.  [Example: if  n
  is  a  variable  of  type  int,  then  new float[n][5]  is well-formed
  (because  n  is  the  expression  of  a  direct-new-declarator),   but
  new float[5][n]   is   ill-formed   (because  n  is  not  a  constant-
  expression).  If n is negative, the effect of new float[n][5] is unde­
  fined.  ]

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

9 Storage for the object created by a new-expression  is  obtained  from
  the  appropriate allocation function (_basic.stc.dynamic.allocation_).
  When the allocation function is called, the first argument will 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 of the global
  allocation      functions      operator new()      for      non-arrays
  (_basic.stc.dynamic_,  _lib.new.delete.single_)  and  operator new[]()
  for arrays (_lib.new.delete.array_).  [Note: A C++ program can provide
  alternative        definitions        of        these        functions
  (_lib.replacement.functions_),    and/or    class-specific    versions
  (_class.free_).   ]  When  the keyword new in a new-expression is pre­
  ceeded by the unary :: operator, the  global  allocation  function  is
  used to allocate the storage.

11The new-placement syntax can be used to supply additional arguments to
  an allocation function.  If used, overloading resolution  is  done  by
  assembling  an  argument  list from the amount of space requested (the
  first argument) and the expressions in the new-placement part  of  the
  new-expression (the second and succeeding arguments).

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  representing  array allocation over­
    head.  They might vary from one use of new to another.  ]

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

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

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

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

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

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

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

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

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

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

17If  the  constructor  exits  using an exception and the new-expression
  does not contain  a  new-placement,  then  the  deallocation  function

  (_basic.stc.dynamic.deallocation_, _class.free_) is called to free the
  memory in which the object was  being  constructed,  after  which  the
  exception continues to propagate in the context of the new-expression.

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

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

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

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

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

  5.3.5  Delete                                            [expr.delete]

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

2 In either alternative, if the value of the operand of  delete  is  the
  null  pointer  the  operation  has no effect.  Otherwise, 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 without
  a  new-placement  specification,  or  a  pointer   to   a   sub-object
  (_intro.object_)   representing   a  base  class  of  such  an  object
  (_class.derived_), or an expression of class type  with  a  conversion
  function  to pointer type (_class.conv.fct_) which yields a pointer to
  such an object.  If not, the behavior is  undefined.   In  the  second

  alternative  (delete  array), the value of the operand of delete shall
  be a pointer to the first element  of  an  array  created  by  a  new-
  expression  without a new-placement specification.  If not, the behav­
  ior is undefined.  [Note: this means that the syntax  of  the  delete-
  expression must match the type of the object allocated by new, not the
  syntax of the new-expression.  ] [Note: a pointer to a const type  can
  be the operand of a delete-expression.  ]

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

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

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

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

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

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

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

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

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

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

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

3 Types shall not be defined in casts.

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

5 The conversions performed by static_cast  (_expr.static.cast_),  rein­
  terpret_cast           (_expr.reinterpret.cast_),           const_cast
  (_expr.const.cast_), or any sequence thereof, can be  performed  using
  the  cast  notation  of  explicit  type conversion.  The same semantic
  restrictions and behaviors apply.  If a given conversion can  be  per­
  formed  using  either static_cast or reinterpret_cast, the static_cast
  interpretation is used.

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

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

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

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

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

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

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

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

5 The restrictions on cv-qualification, and the manner in which the  cv-
  qualifiers  of  the operands are combined to produce the cv-qualifiers
  of the  result,  are  the  same  as  the  rules  for  E1.E2  given  in
  _expr.ref_.

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

  5.6  Multiplicative operators                               [expr.mul]

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

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

3 The binary * operator indicates multiplication.

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

  5.7  Additive operators                                     [expr.add]

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

2 For subtraction, one of the following shall hold:

  --both operands have arithmetic or enumeration type;

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

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

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

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

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

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

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

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

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

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

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

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

  5.9  Relational operators                                   [expr.rel]

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

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

    that  is,  p<=q  and  p>=q  yield  false,  and p<q and p>q result in
    unspecified behavior.

  --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 members of the same object sepa­
    rated 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.  Pointer to member
  conversions (_conv.mem_) are performed to bring them to the same type,
  which shall be a cv-qualified or cv-unqualified version of the type of
  one of the operands.  [Note: this implies that any pointer  to  member
  can be compared to an integral constant expression evaluating to zero.
  ] If both operands are null, they compare equal.   Otherwise  if  only
  one  is  null, they compare unequal.  Otherwise if either is a pointer
  to a virtual member function, the result  is  unspecified.   Otherwise
  they  compare equal if and only if they would refer to the same member
  of the same most derived object (_intro.object_) or the same subobject
  if they were dereferenced with a hypothetical object of the associated
  class type.  [Example:
          struct B {
                  int f();
          };
          struct L : B { };
          struct R : B { };
          struct D : L, R { };

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

  5.11  Bitwise AND operator                              [expr.bit.and]

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

  5.12  Bitwise exclusive OR operator                         [expr.xor]

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

  5.13  Bitwise inclusive OR operator                          [expr.or]

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

  5.14  Logical AND operator                              [expr.log.and]

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

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

  5.15  Logical OR operator                                [expr.log.or]

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

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

  5.16  Conditional operator                                 [expr.cond]

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

2 If the second and the third operands are lvalues  and  have  the  same
  type  (before  any  implicit  conversions), the result is an lvalue of
  that type.  Otherwise, if the second and the third operands are  lval­
  ues  of  class  type,  and if one operand is of a class type that is a
  base class of the type of the other operand (before any implicit  con­
  versions),  the  operands  are  implicitly  converted to a common type
  (which shall be a cv-qualified or cv-unqualified version of  the  type
  of  either  the  second  or third operand) as if by a static_cast to a
  reference to the common type (_expr.static.cast_).  [Note:  this  con­
  version  will  be  ill-formed  if  the  base  class is inaccessible or
  ambiguous.  ] The result is an lvalue of the common type.   Otherwise,
  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.

3 If  either  the  second  or  third  expression  is  a throw-expression
  (_except.throw_), the result is of the type of the other.  If both the
  second  and  third  expression are throw-expressions, the result is of
  the type void.  Otherwise, if both the second and  the  third  expres­
  sions  are  of arithmetic or enumeration type, then if they are of the
  same type the result is of that type; otherwise the  usual  arithmetic
  conversions  are performed to bring them to a common type.  Otherwise,
  if both the second and the third expressions are either a pointer or a
  null  pointer constant, pointer conversions (_conv.ptr_) are performed
  to bring them to a common type, which shall be a cv-qualified  or  cv-

  unqualified  version  of  the  type  of either the second or the third
  expression.  Otherwise, if both the second and the  third  expressions
  are  either a pointer to member or a null pointer constant, pointer to
  member conversions (_conv.mem_) are performed to bring them to a  com­
  mon type14) which shall be a cv-qualified or cv-unqualified version of
  the  type of either the second or the third expression.  Otherwise, if
  both the second and the third expressions are of the same class T, the
  common type is T.  Otherwise, if both the second and the third expres­
  sions have type "cv void", the common type is  "cv  void."   Otherwise
  the  expression  is  ill-formed.  The result has the common type; only
  one of the second and third expressions is evaluated.

  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 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
  _________________________
  14)  This  is one instance in which the "composite type", as described
  in the C Standard, is still employed in C++.

  shall either have arithmetic or enumeration type or be a pointer to  a
  possibly  cv-qualified  completely  defined object type.  In all other
  cases, E1 shall have arithmetic type.

8 See _except.throw_ for throw expressions.

  5.18  Comma operator                                      [expr.comma]

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

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

  5.19  Constant expressions                                [expr.const]

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

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

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

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

  --an arithmetic constant expression,

  --an address constant expression,

  --a reference constant expression,

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

  --a pointer to member constant expression.

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

4 An address constant expression is a pointer to an  lvalue  designating
  an object of static storage duration or a function.  The pointer shall
  be created explicitly, using the unary & operator, or implicitly using
  an  expression of array (_conv.array_) or function (_conv.func_) type.
  The subscripting 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 constant expression,
  even if the function is inline and has a reference return type.

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

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