______________________________________________________________________

  5   Expressions                                       [expr]

  ______________________________________________________________________

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

2 Operators  can  be  overloaded, that is, given meaning when applied to
  expressions of class type (_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_).1)

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 Operators can be regrouped according to the usual  mathematical  rules
  only where the operators really are associative or commutative.  Over­
  loaded operators are never assumed to be associative  or  commutative.
  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.  For 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

  _________________________
  1) Nor is it guaranteed for type bool; the left operand  of  +=  shall
  not have type bool.

5 The  handling  of overflow and divide by zero in expression evaluation
  is implementation dependent.  Most  existing  implementations  of  C++
  ignore  integer  overflows.   Treatment  of  division  by zero and all
  floating  point  exceptions  vary  among  machines,  and  is   usually
  adjustable by a library function.

6 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.  Such
  uses do not count as standard conversions when considering overloading
  resolution (_over.match_).

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 analy­
  sis,  the  expression designates the object or function denoted by the
  reference, and the expression  is  an  lvalue.   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 or enum types to and from fundamen­
  tal types, pointers, and so on, can  be  defined  (_class.conv_).   If
  unambiguous  (_over.match_),  such  conversions will be applied by the
  compiler 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 conversion  will  be  applied  to  convert  the
  expression 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.

  +-------                 BEGIN BOX 1                -------+
  Enumerations are handled correctly by  the  usual  arithmetic  conver­
  sions,  and  for  any  operator  that invokes the integral promotions.
  However, there may be other places in this Clause that fail  to  treat
  enumerations appropriately.
  +-------                  END BOX 1                 -------+

12
  --If  either operand is of type long double, the other is converted to
    long double.

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

    double.

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

  --Otherwise, the integral promotions (_conv.prom_)  are  performed  on
    both operands.2)

  --Then, if either operand is unsigned long the other is  converted  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 is converted to a long int; otherwise both operands
    are converted to unsigned long int.

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

  --Otherwise,  if either operand is unsigned, the other is converted to
    unsigned.

  --Otherwise, both operands are int.

13If the program attempts to  access  the  stored  value  of  an  object
  through an lvalue of other than one of the following types:

  --the dynamic type of the object,

  --a qualified version of the declared type of the object,

  --a  type  that  is  the  signed or unsigned type corresponding to the
    declared type of the object,

  --a type that is the signed or unsigned type corresponding to a quali­
    fied version of the declared type of the object,

  --an  aggregate  or union type that includes one of the aforementioned
    types among its members (including, recursively, a member of a  sub­
    aggregate or contained union),

  --a  type  that  is  a  (possibly  qualified)  base  class type of the
    declared type of the object,

  --a character type.3) the result is undefined.

  _________________________
  2)  As a consequence, operands of type bool, wchar_t, or an enumerated
  type are converted to some integral type.
  3) The intent of this list is to specify those circumstances in  which
  an object may or may not be aliased.

  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

2 A literal is a primary expression.   Its  type  depends  on  its  form
  (_lex.literal_).

3 In the body of a nonstatic member function (_class.mfct_), the keyword
  this names a pointer to the object for which the function was invoked.
  The  keyword  this  shall  not be used outside a class member function
  body.

  +-------                 BEGIN BOX 2                -------+
  In a  constructor  it  is  common  practice  to  allow  this  in  mem-
  initializers.
  +-------                  END BOX 2                 -------+

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  is.   The identifier or operator-
  function-id shall be of namespace scope.  Use of :: allows a type,  an
  object,  a  function,  or  an enumerator to be referred to even if its
  identifier has been hidden (_basic.scope_).

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

6 A  id-expression is a restricted form of a primary-expression that can
  appear after . and -> (_expr.ref_):
          id-expression:
                  unqualified-id
                  qualified-id

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

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

7 An  identifier  is  an  id-expression  provided  it  has been suitably
  declared (_dcl.dcl_).   For  operator-function-ids,  see  _over.oper_.
  For  conversion-function-ids, see _class.conv.fct_.  A class-name pre­
  fixed by ~ denotes a destructor; see _class.dtor_.
          qualified-id:
                  nested-name-specifier unqualified-id

8 A nested-name-specifier that names a class (_dcl.type_) followed by ::
  and the name of a member of that class (_class.mem_), or a member of a
  base of that class (_class.derived_), is a qualified-id; its  type  is
  the  data  member  type  or  function member type; it is not an object
  type.  The result is the member.  The result is an lvalue if the  mem­
  ber  is.   The  class-name might be hidden by a nontype name, in which
  case the class-name is still found  and  used.   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_).   Multiply
  qualified names, such as N1::N2::N3::n, can be used to refer to nested
  types (_class.nest_).

9 In 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.  For the purpose of this
  evaluation, the name, if any, of  each  class  is  also  considered  a
  nested class member of that class.

  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 . id-expression
                  postfix-expression -> 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.  The intuitive meaning is  that  of  a  subscript.
  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 complete.  The expression E1[E2] is iden­
  tical  (by  definition)  to  *((E1)+(E2)).    See   _expr.unary_   and
  _expr.add_  for  details  of  *  and  + and _dcl.array_ for details of
  arrays.

  5.2.2  Function call                                       [expr.call]

1 There are two kinds of function call: ordinary function call and  mem­
  ber function4) (_class.mfct_) call.  A  function  call  is  a  postfix
  expression followed by parentheses containing a possibly empty, comma-
  separated list of expressions which constitute the  arguments  to  the
  function.  For ordinary function call, the postfix expression shall be
  a function name, or a pointer or reference to  function.   For  member
  function   call,   the   postfix   expression  shall  be  an  implicit
  (_class.mfct_) or explicit class member access (_expr.ref_) whose  id-
  expression  is  a function member name, or a pointer-to-member expres­
  sion  (_expr.mptr.oper_)  selecting  a  function  member.   The  first
  expression in the postfix expression is then called the object expres­
  sion, 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.  That is, a member function call
  of  the form f() is interpreted as this->f() (see _class.this_).  If a
  function or member function name is used, the name can  be  overloaded
  (_over_),  in  which  case  the  appropriate function will be selected
  according to the rules in _over.match_.  The function called in a mem­
  ber function call is normally selected according to the static type of
  the object expression (see _class.derived_), but if that  function  is
  virtual  the  function  actually  called  will  be the final overrider
  (_class.virtual_) of the selected function in the dynamic type of  the
  object expression (i.e., the type of the object pointed or referred to
  by  the  current  value  of  the  object  expression).   _class.cdtor_
  describes  the  behavior  of  virtual  function calls when the object-
  expression refers to an object under construction or destruction.

2 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 complete or the type void.

  _________________________
  4)  A static member function (_class.static_) is an ordinary function.

3 When  a  function is called, each parameter (_dcl.fct_) is initialized
  (_dcl.init.ref_, _class.copy_, _class.ctor_)  with  its  corresponding
  argument.   Standard  (_conv_) and user-defined (_class.conv_) conver­
  sions are performed.  The value  of  a  function  call  is  the  value
  returned  by  the called function except in a virtual function call if
  the return type of the final overrider is different  from  the  return
  type  of  the  statically chosen function, the value returned from the
  final overrider is converted to the return type of the statically cho­
  sen  function.   A  function  can change the values of its nonconstant
  parameters, but these changes cannot affect the values  of  the  argu­
  ments  except  where  a  parameter  is  of  a non-const reference type
  (_dcl.ref_).  Where a parameter is of reference type a temporary vari­
  able is introduced if needed (_dcl.type_, _lex.literal_, _lex.string_,
  _dcl.array_, _class.temporary_).  In addition, it is possible to  mod­
  ify the values of nonconstant objects through pointer parameters.

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

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

6 Any  argument  of  type  float for which there is no parameter is con­
  verted to double before the call; any of char, short, or  a  bit-field
  type  for which there is no parameter are converted to int or unsigned
  by integral promotion (_conv.prom_).  Any argument of enumeration type
  is converted to int, unsigned, long, or unsigned long by integral pro­
  motion.  An object of a class for which no parameter  is  declared  is
  passed as a data structure.

  +-------                 BEGIN BOX 4                -------+
  To  ``pass  a parameter as a data structure'' means, roughly, that the
  parameter must be a PODS, and that otherwise  the  behavior  is  unde­
  fined.  This must be made more precise.
  +-------                  END BOX 4                 -------+

7 An  object  of  a class for which a parameter is declared is passed by
  initializing the parameter with the argument  by  a  constructor  call
  before the function is entered (_class.temporary_, _class.copy_).

8 The  order  of  evaluation of arguments is unspecified; take note that
  compilers differ.  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 The function-to-pointer  standard  conversion  (_conv.func_)  is  sup­
  pressed on the postfix expression of a function call.

10Recursive calls are permitted.

11A  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 A simple-type-specifier (_dcl.type_) followed by  a  (empty)  pair  of
  parentheses  constructs a value of the specified type.  If the type is
  a class with a default constructor  (_class.ctor_),  that  constructor
  will  be  called; otherwise the result is the default value given to a
  static object of the specified type.  See also (_expr.cast_).

  5.2.4  Class member access                                  [expr.ref]

1 A postfix expression followed by a dot .)  or an arrow ->) followed by
  an  id-expression  is  a  postfix  expression.  The postfix expression
  before the dot or arrow is evaluated;5) the result of that evaluation,
  together  with  the  id-expression, determine the result of the entire
  postfix expression.

2 For the first option (dot) the  type  of  the  first  expression  (the
  object  expression)  shall  be class object (of a complete type).  For
  the second option (arrow)  the  type  of  the  first  expression  (the
  pointer  expression)  shall  be pointer to class object (of a complete
  type).  The id-expression shall name a member of  that  class,  except
  that  an  imputed  destructor can be explicitly invoked for a built-in
  type (_class.dtor_).  Therefore, if E1 has the type pointer  to  class
  X,  then  the  expression  E1->E2  is converted to the equivalent form
  (*(E1)).E2; the remainder of this  subclause  will  address  only  the
  first option (dot)6).

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,
  _________________________
  5) This evaluation happens even if the result is unnecessary to deter­
  mine  the  value  of the entire postfix expression, for example if the
  id-expression denotes a static member.
  6) Note that if E1 has the type pointer to class X, then (*(E1)) is an
  lvalue.

  the  name  is  looked  up  in the context in which the entire postfix-
  expression occurs.  If nested-name-specifier of the qualified-id spec­
  ifies  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.  For the purpose of this type lookup, the  name,  if  any,  of
  each  class  is  also  considered a nested class member of that class.
  These searches shall yield a single  type  which  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).  For the purpose of this evaluation, the name, if any, of
  each class is also considered a nested class member of that class.

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
    class.  The type of E1.E2 is T.

  --If  E2  is  a  (possibly overloaded) static member function, and the
    type of E2 is cv 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
    cv 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 member, 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 cv function of (parameter type list) 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  func­
    tion  shall  be  at  least as cv-qualified as the left-hand operand.
    The type of E1.E2 is class X's cv member function of (parameter type
    list) returning T.

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

  --If  E2 is a member constant, and the type of E2 is T, the expression
    E1.E2 is not an lvalue.  The type of E1.E2 is T.

7 Note that class objects can be  structures  (_class.mem_)  and  unions
  (_class.union_).  Classes are discussed in _class_.

  5.2.5  Increment and decrement                        [expr.post.incr]

1 The  value  obtained by applying a postfix ++ is (a copy of) the value
  that the operand had before applying the operator.  The operand  shall
  be  a  modifiable  lvalue.  The type of the operand shall be an arith­
  metic 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 (this  use  is
  deprecated).   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 unique7) B sub-object of the D object
  referred  to by v.  In both the pointer and reference cases, cv1 shall
  be the same cv-qualification as,  or  greater  cv-qualification  than,
  cv2,  and  B shall be an accessible nonambiguous base class of D.  For
  example,
          struct B {};
          struct D : B {};
          void foo(D* dp)
          {
              B*  bp = dynamic_cast<B*>(dp);  // equivalent to B* bp = dp;
          }

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 com­
  plete object (_class.base.init_) pointed to by v.  Otherwise,  a  run-
  time check is applied to see if the object pointed or referred to by v
  can be converted to the type pointed or referred to by T.

8 The run-time check logically executes like this: If, in  the  complete
  object pointed (referred) to by v, v points (refers) to an unambiguous
  base class sub-object of a T object,  the  result  is  a  pointer  (an
  lvalue  referring)  to  that  T object.  Otherwise, if the type of the
  complete object has an unambiguous public base class of  type  T,  the
  result  is  a  pointer (reference) to the T sub-object of the complete
  object.  Otherwise, the run-time check fails.

  +-------                 BEGIN BOX 5                -------+
  Comment from Bill Gibbons: the  original  papers  allowed  all  strict
  downcasts  from  accessible  bases.  This wording does not.  The para­
  graph can be fixed by changing the first instance  of  ``an  unambigu­
  ous'' to ``a public.''
  +-------                  END BOX 5                 -------+

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_).  For example,

  _________________________
  7) The complete object pointed or referred to by v can contain other B
  objects as base classes, but these are ignored.

          class A { virtual void f(); };
          class B { virtual void g(); };
          class D : public virtual A, private B {};
          void g()
          {
              D   d;
              B*  bp = (B*)&d;  // cast needed to break protection
              A*  ap = &d;      // public derivation, no cast needed
              D&  dr = dynamic_cast<D&>(*bp);  // 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*  ep = dynamic_cast<E*>(ap);  // succeeds
          }
  _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 of  type  const type_info&.   The
  value is a reference to a type_info object (_lib.type.info_) that rep­
  resents the type-id or the type of the expression respectively.

2 If  the  expression   is   a   reference   to   a   polymorphic   type
  (_class.virtual_),    the    type_info   for   the   complete   object
  (_class.base.init_) referred to is the result.

3 If the expression is the result of applying unary * to a pointer to  a
  polymorphic type,8) then the pointer shall either be zero or point  to
  a  valid object.  If the pointer is zero, the typeid expression throws
  the bad_typeid exception (_lib.bad.typeid_).  Otherwise, the result of
  the  typeid  expression  is  the value that represents the type of the
  complete object to which the pointer points.

4 If the  expression  is  the  result  of  subscripting  (_expr.sub_)  a
  pointer,  say  p, that points to a polymorphic type,9) then the result
  of the typeid expression is that of typeid(*p).  The subscript is  not
  _________________________
  8)  If  p is a pointer, then *p, (*p), ((*p)), and so on all meet this
  requirement.
  9)  If p is a pointer to a polymorphic type and i has integral or enu­
  merated type,  then  p[i],  (p[i]),  (p)[i],  ((((p))[((i))])),  i[p],
  (i[p]), and so on all meet this requirement.

  evaluated.

5 If  the  expression is neither a pointer nor a reference to a polymor­
  phic type, the result is the type_info representing the (static)  type
  of the expression.  The expression is not evaluated.

6 In  all  cases  typeid  ignores  the  top-level  cv-qualifiers  of its
  operand's type. For 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
  _class.cdtor_ describes the behavior of typeid applied  to  an  object
  under construction or destrcution.

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

2 Any  implicit  conversion (including standard conversions and/or user-
  defined conversions; see _conv_ and _over.best.ics_) can be  performed
  explicitly  using  static_cast.  More precisely, if T t(v); is a well-
  formed declaration, for some invented temporary variable t,  then  the
  result  of  static_cast<T>(v) is defined to be the temporary t, and is
  an lvalue if T is a reference type,  and  an  rvalue  otherwise.   The
  expression v shall be an lvalue if the equivalent declaration requires
  an lvalue for v.

3 If the static_cast does not correspond to an  implicit  conversion  by
  the  above  definition, it 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 expression of type T1 can be cast to the type  reference  to
  T2  if an expression of type pointer to T1 can be explicitly converted
  to the type pointer to T2 using a static_cast.  That is,  a  reference
  cast   static_cast<T&>x   has   the  same  effect  as  the  conversion
  *static_cast<T*>&x with the built-in & and * operators.  The result is
  an   lvalue.   This  interpretation  is  used  only  if  the  original
  static_cast is not well-formed as an  implicit  conversion  under  the
  rules given above.  This form of reference cast creates an lvalue that
  refers to the same object as the source lvalue, but with  a  different
  type.   Consequently,  it  does  not  create  a  temporary or copy the
  object,  and  constructors  (_class.ctor_)  or  conversion   functions

  (_class.conv_) are not called.  For example,
          struct B {};
          struct D : public B {};
          D d;
          // creating a temporary for the B sub-object not allowed
          ... (const B&) d ...

6 The  inverse  of  any  standard  conversion  (_conv_) 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 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 or  inher­
  its the original member, the resulting pointer to member points to the
  member in class B.  Otherwise, the result of the cast is undefined.

  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; see
  _expr.const.cast_.

3 The mapping performed by reinterpret_cast  is  implementation-defined;
  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,
  but 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 that differs from the type used
  in the definition of the function is undefined.  See also  _conv.ptr_.

8 A  pointer to an object can be explicitly converted to a pointer to an
  object of different type.  In general, the results of this are unspec­
  ified;  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.

  +-------                 BEGIN BOX 6                -------+
  This does not allow conversion of function pointers to other  function
  pointer types and back.  Should it?
  +-------                  END BOX 6                 -------+

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 explicitly
  converted  to  an rvalue of type pointer to member of Y of type T2, if
  T1 and T2 are both member function types or both  data  member  types.
  The  null  member  pointer value (_conv.mem_) is converted to the null
  member pointer value of the destination type.  In general, the  result
  of this conversion is unspecified, except that:

  --converting an rvalue of type pointer to member function to a differ­
    ent 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 that differs from the function type specified  on  the
  member function declaration results in undefined behavior.

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  converted
  to the type pointer to T2 using a reinterpret_cast.  That is, a refer­
  ence 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 created, 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
  +-------                 BEGIN BOX 7                -------+
  Editorial  change  from  previous  edition:  it  is  permitted  to use
  const_cast as a no-op.
  +-------                  END BOX 7                 -------+

  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 and  where  cv1  and
  cv2  are  cv-qualifications  ,  using the cast const_cast<cv2 T*>.  An
  lvalue of type cv1 T can be explicitly converted 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 explic­
  itly 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 The following rules define casting away constness.  In these rules  Tn
  and Xn represent types.  For two pointer types:
            Kismin(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 from:

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

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

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

6 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 const­
  ness if a cast from an rvalue of  type  pointer  to  T1  to  the  type
  pointer to T2 casts away constness.

7 Note  that  these  rules  are not intended to protect constness in all
  cases.  For instance, conversions between pointers  to  functions  are
  not  covered  because such conversions lead to values whose use causes
  undefined behavior.  For the same reasons, conversions between  point­
  ers  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.

8 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   constness   may   produce   undefined   behavior
  (_dcl.type.cv_).

  +-------                      BEGIN BOX 8                     -------+
  This will need to be reworked once the memory model and  object  model
  are ironed out.
  +-------                       END BOX 8                      -------+

9 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.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,  and the result is an lvalue referring to the object to which
  the expression points.  If the type of the expression is pointer to T,
  the type of the result is T.

2 The  result  of the unary & operator is a pointer to its operand.  The
  operand shall be an lvalue or a qualified-id.  In the first  case,  if
  the  type of the expression is T, the type of the result is pointer to
  T.  In particular, the address of an object of type cv T is pointer to
  cv  T,  with  the  same cv-qualifiers.  For example, the address of an
  object of type const int has type pointer to const int.  For a  quali­
  fied-id, if the member is a nonstatic member of class C of type T, the
  type of the result is pointer to member of class C  of  type  T.   For
  example:
          struct A { int i; };
          struct B : A { };
          ... &B::i ... // has type "int A::*"
  For  a  static member of type T, the type is plain pointer to T.  Note
  that a pointer to member is only formed when an explicit & is used and
  its  operand is a qualified-id not enclosed in parentheses.  For exam­
  ple,  the  expression  &(qualified-id),  where  the  qualified-id   is
  enclosed  in  parentheses, does not form an expression of type pointer
  to member.  Neither does qualified-id, and there is no  implicit  con­
  version from the type 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 &unqualified-id a
  pointer to member, even within the scope of unqualified-id's class.

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

3 The  address of an object of incomplete type can be taken, but only if
  the complete type of that object does not have the address-of operator
  (operator&()) overloaded; no diagnostic is required.

4 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 that since the context
  might determine whether the operand is a static  or  nonstatic  member
  function,  the context can also affect whether the expression has type
  pointer to function or pointer to member function.

5 The operand of the unary + operator shal have arithmetic, enumeration,
  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.

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

7 The operand of the logical negation operator !  is converted  to  bool
  (_conv.bool_); its value is true if the converted operand is false and
  false otherwise.  The type of the result is bool.

8 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.  See the discussions of addition
  (_expr.add_) and assignment operators (_expr.ass_) for information  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 size, in bytes, of  its  operand.   The
  operand  is  either an expression, which is not evaluated, or a paren­
  thesized type-id.  The sizeof operator shall  not  be  applied  to  an
  expression  that  has function or incomplete type, or to the parenthe­
  sized name of such a type, or to an  lvalue  that  designates  a  bit-
  field.   A  byte is unspecified by the language except in terms of the
  value  of  sizeof;   sizeof(char)   is   1,   but   sizeof(bool)   and
  sizeof(wchar_t) are implementation-defined.  10)

2 When  applied to a reference, the result is the size of the referenced
  object.  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.

  _________________________
  10) 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 type size_t,  an  implementation-dependent
  unsigned   integral   type  defined  in  the  standard  header  <cstd­
  def>(_lib.support.types_).

  5.3.4  New                                                  [expr.new]

1 The new-expression  attempts  to  create  an  object  of  the  type-id
  (_dcl.name_)  to  which  it is applied.  This type shall be a complete
  object or array type (_intro.memory_, _basic.types_).
          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:
                  * cv-qualifier-seqopt new-declaratoropt
                   ::opt nested-name-specifier * cv-qualifier-seqopt 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_).  That is, the lifetime of such an entity is not
  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.  For 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.  For example,

4         new int(*[10])();       // error
  is ill-formed because the binding is
          (new int) (*[10])();    // error
  The explicitly parenthesized version of the new operator can  be  used
  to create objects of compound types (_basic.compound_).  For example,
          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.  Thus, 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.  For 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,
  an array with no elements is allocated.  The pointer returned  by  the
  new-expression  will  be 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
  amount  of space requested (which might be larger than the size of the
  object being created only if that object is an array).

10An implementation provides default definitions of the  global  alloca­
  tion functions operator new() for non-arrays (_lib.new.delete.single_)
  and operator new[]() for arrays (_lib.new.delete.array_).  A C++  pro­
  gram   can   provide   alternative   definitions  of  these  functions
  (_lib.replacement.functions_),    and/or    class-specific    versions
  (_class.free_).

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

12For 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 return value from the allocation function, if  non-null,  will  be
  assumed to point to a block of appropriately aligned available storage
  of the requested size, and the object will be created  in  that  block
  (but  not  necessarily at the beginning of the block, if the object is
  an array).

14A new-expression for a class  calls  one  of  the  class  constructors
  (_class.ctor_)  to  initialize i the object.  An object of a class can
  be created by new only if suitable  arguments  are  provided  for  the
  class'  constructors  by  the  new-initializer,  or if the class has a
  default  constructor.11) If no user-declared constructor is used and a
  new-initializer is provided, the new-initializer shall be of the  form
  (expression) or (); if the expression is present, it shall be of class
  type and is used to initialize the object.

15No initializers can be specified for arrays.  Arrays of objects  of  a
  class  can  be  created  by  a  new-expression only if the class has a
  default constructor.12) In that case, the default constructor will  be
  called  for each element of the array, in order of increasing address.

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

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

18If the constructor throws an exception and the new-expression does not
  contain   a   new-placement,   then    the    deallocation    function
  (_basic.stc.dynamic.deallocation_,  _class.free_)  is used 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.

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

  +-------                     BEGIN BOX 10                     -------+
  This is a correction to San Diego resolution 3.5, which  on  its  face
  seems  to  require  that  whether  to  use  delete or delete[] must be
  decided purely on syntactic grounds.  I believe the intent of the com­
  mittee  was  to  make the form of delete correspond to the form of the
  corresponding new.
  +-------                      END BOX 10                      -------+
  _________________________
  11) This means that struct s{}; s* ps =  new  s;  is  allowed  on  the
  grounds that class s has an implicitly-declared default constructor.
  12) PODS structs have an implicitly-declared default constructor.

20Whether the allocation function is called before evaluating  the  con­
  structor  arguments,  after  evaluating  the constructor arguments but
  before entering the constructor,  or  by  the  constructor  itself  is
  unspecified.   It  is also unspecified whether the arguments to a con­
  structor are evaluated if the allocation  function  returns  the  null
  pointer or throws an exception.

  5.3.5  Delete                                            [expr.delete]

1 The    delete-expression   operator   destroys   a   complete   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 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_).

  +-------                     BEGIN BOX 11                     -------+
  Issue: ... or a class with an unambiguous conversion to such a pointer
  type ...
  +-------                      END BOX 11                      -------+

  In the second alternative (delete array), the value of the operand  of
  delete  shall  be  a  pointer  to an array created by a new-expression
  without a new-placement specification.

3 In the first alternative (delete object), if the static  type  of  the
  operand is different from its dynamic type, the static type shall have
  a virtual destructor or the result is undefined.  In the second alter­
  native  (delete array) if the dynamic type of the object to be deleted
  is a class that has a destructor and its static type is different from
  its dynamic type, the result is undefined.

  +-------                     BEGIN BOX 12                     -------+
  This  should  probably  be  tightened  to  require that the static and
  dynamic types match, period.
  +-------                      END BOX 12                      -------+

4 The deletion of an object might change its value.  If  the  expression
  denoting the object in a delete-expression is a modifiable lvalue, any
  attempt  to  access  its  value  after  the  deletion   is   undefined
  (_basic.stc.dynamic.deallocation_).

5 If the class of the object being deleted is incomplete at the point of
  deletion and the class has a destructor or an allocation function or a

  deallocation function, the result 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).

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

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

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

1 The  result  of  the  expression (T) cast-expression is of type T.  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

2 Types shall not be defined in casts.

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

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

5 In  addition to those conversions, a pointer to an object of a derived
  class (_class.derived_) can be explicitly converted to  a  pointer  to
  any  of  its  base  classes  regardless  of accessibility restrictions
  (_class.access.base_),  provided   the   conversion   is   unambiguous
  (_class.member.lookup_).  The resulting pointer will refer to the con­
  tained object of the base class.

  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  unambiguous
  and  accessible  base class.  The result is an object or a function of
  the type specified by the second operand.

4 If the result of .*  or ->* is a function, then  that  result  can  be
  used only as the operand for the function call operator ().  For exam­
  ple,
          (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 result
  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 type; the operands of  %
  shall  have  integral type.  The usual arithmetic conversions are per­
  formed 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 result  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 dependent.

  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 type, or  one
  operand shall be a pointer to a completely defined object type and the
  other shall have integral type.

2 For subtraction, one of the following shall hold:

  --both operands have arithmetic type;

  --both operands are pointers to qualified or unqualified  versions  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 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.

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)

  5.8  Shift operators                                      [expr.shift]

1 The shift operators << and >> group left-to-right.
          shift-expression:
                  additive-expression
                  shift-expression << additive-expression
                  shift-expression >> additive-expression
  The  operands  shall  be  of integral type and integral promotions are
  performed.  The type of the  result  is  that  of  the  promoted  left
  operand.  The result is undefined if the right operand is negative, or
  greater than or equal to the length  in  bits  of  the  promoted  left
  operand.   The  value of E1 << E2 is E1 (interpreted as a bit pattern)
  left-shifted E2 bits; vacated bits are zero-filled.  The value  of  E1
  >>  E2 is E1 right-shifted E2 bit positions.  The right shift is guar­
  anteed to be logical (zero-fill) if E1 has an unsigned type or  if  it
  has  a  nonnegative  value;  otherwise  the  result  is implementation
  _________________________
  13) Another way to approach pointer arithmetic is first to convert the
  pointer(s) to character pointer(s): In this scheme  the  integral  ex­
  pression  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 character point­
  ers  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.

  dependent.

  5.9  Relational operators                                   [expr.rel]

1 The relational operators group left-to-right, but  this  fact  is  not
  very useful; 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 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 arithmetic operands.
  Pointer conversions are performed on pointer operands to bring them to
  the same type, which shall be a qualified or  unqualified  version  of
  the type of one of the operands.  This implies that any pointer can be
  compared to an integral constant expression evaluating to zero and any
  pointer  can be compared to a pointer of qualified or unqualified type
  void* (in the latter case the pointer is first  converted  to  void*).
  Pointers  to objects or functions of the same type (after pointer con­
  versions) can be compared; the result depends on  the  relative  posi­
  tions of the pointed-to objects or functions in the address space.

3 If two pointers 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.  If two pointers of the same type point to differ­
  ent objects or functions, or only one of them is  null,  they  compare
  unequal.   If two pointers point to nonstatic data members of the same
  object, the pointer to the later declared member compares higher  pro­
  vided  the  two  members  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 separated by an
  access-specifier label (_class.access.spec_) the  result  is  unspeci­
  fied.   If  two pointers point to data members of the same union, 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  com­
  pares higher.  Other pointer comparisons are implementation-defined.

  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.
  (Thus a<b == c<d is true whenever a<b and c<d  have  the  same  truth-

  value.)

2 In  addition,  pointers  to  members of the same type can be compared.
  Pointer to member conversions (_conv.mem_) are performed.   A  pointer
  to  member  can  be  compared  to an integral constant expression that
  evaluates to zero.  If one operand is a pointer to  a  virtual  member
  function  and  the  other is not the null pointer to member value, the
  result is unspecified.

  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
  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 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 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 converted
  to  type  bool (_conv.bool_).  The result is true if both operands are
  true and false otherwise.  Unlike &, && guarantees left-to-right eval­
  uation:  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 converted
  to  bool  (_conv.bool_).  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
  converted  to  bool (_conv.bool_).  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 either  the  second  or  third  expression  is  a  throw-expression
  (_except.throw_), the result is of the type of the other.

3 If  both  the second and the third expressions are of arithmetic type,
  then if they are of the same type the result is of that  type;  other­
  wise 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 an integral constant expression that evaluates
  to zero, pointer conversions (_conv.ptr_) are performed to bring  them
  to a common type, which shall be a qualified or 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 mem­
  ber or an integral constant expression that evaluates to zero, pointer
  to  member  conversions  (_conv.mem_) are performed to bring them to a
  common  type14)  which  shall be a qualified or unqualified version of
  the type of either the second or the third expression.  Otherwise,  if
  both the second and the third expressions are lvalues of related class
  types, they are converted to a common type as if by a cast to a refer­
  ence  to the common type (_expr.static.cast_).  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 expressions
  _________________________
  14) This is one instance in which the composite type, as described  in
  the C Standard, is still employed in C++.

  have type cv void, the common type is cv void.  Otherwise the  expres­
  sion  is  ill formed.  The result has the common type; only one of the
  second and third expressions is evaluated.  The result is an lvalue if
  the  second  and  the third operands are of the same type and both are
  lvalues.

  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
                  unary-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  converted
  to the unqualified type of the left operand using standard conversions
  (_conv_) and/or user-defined conversions (_class.conv_), as necessary.

4 Assignment  to  objects of a class (_class_) X is defined by the func­
  tion  X::operator=()  (_over.ass_).   Unless  the  user   defines   an
  X::operator=(),   the   default   version   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.  E1 shall not  have
  bool  type.  In += and -=, E1 can be a pointer to a possibly-qualified
  completely defined object type, in which case E2 shall  have  integral
  type  and is converted as explained in _expr.add_; In all other cases,
  E1 and E2 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
  of the left expression are performed  before  the  evaluation  of  the
  right  expression.   The type and value of the result are the type and
  value of the right operand; the result  is  an  lvalue  if  its  right
  operand is.

2 In  contexts  where  comma is given a special meaning, for example, in
  lists of arguments to functions (_expr.call_) and lists of  initializ­
  ers  (_dcl.init_),  the comma operator as described in this clause can
  appear only in parentheses; for 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  constant:  as  array  bounds  (_dcl.array_), as case expressions
  (_stmt.switch_), as bit-field lengths (_class.bit_), and as enumerator
  initializers (_dcl.enum_).
          constant-expression:
                  conditional-expression
  An    integral   constant-expression   can   involve   only   literals
  (_lex.literal_), enumerators, const values of integral types  initial­
  ized  with  constant expressions (_dcl.init_), and sizeof expressions.
  Floating constants (_lex.fcon_) can appear only if they  are  cast  to
  integral  types.  Only type conversions to integral 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 constant (_conv.ptr_),

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

  --an arithmetic constant expression,

  --an address constant,

  --an  address  constant  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 type and shall
  only  have  operands that are integer constants (_lex.icon_), floating
  constants (_lex.fcon_), enumerators, character constants  (_lex.ccon_)
  and  sizeof expressions (_expr.sizeof_).  Casts operators in an arith­
  metic constant expression  shall  only  convert  arithmetic  types  to
  arithmetic types, except as part of an operand to the sizeof operator.

4 An address constant 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 expres­
  sion of array (_conv.array_) or function (_conv.func_) type.  The sub­
  scripting 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  con­
  stant,  but the value of an object shall not be accessed by the use of
  these operators.  An expression that designates the address of a  mem­
  ber  or  base  class  of  a non-POD class object (_class_) is never 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 pointer to member constant expression shall  be  created  using  the
  unary  & operator applied to a qualified-id operand (_expr.unary.op_).