______________________________________________________________________

  3   Basic concepts                                   [basic]

  ______________________________________________________________________

1 [Note: this clause presents the basic concepts of  the  C++  language.
  It  explains  the difference between an object and a name and how they
  relate to the notion of an lvalue.  It introduces the  concepts  of  a
  declaration and a definition and presents C++'s notion of type, scope,
  linkage, and storage duration.  The mechanisms for starting and termi­
  nating  a  program  are  discussed.  Finally, this clause presents the
  fundamental types of the language and lists the ways  of  constructing
  compound types from these.

2 This  clause does not cover concepts that affect only a single part of
  the language.  Such concepts are discussed in the relevant clauses.
  --end note]

3 An  entity  is a value, object, subobject, base class subobject, array
  element, variable, function, set of functions, instance of a function,
  enumerator, type, class member, template, or namespace.

4 A  name  is a use of an identifier (_lex.name_) that denotes an entity
  or label (_stmt.goto_, _stmt.label_).

  +-------                 BEGIN BOX 1                -------+
  We need to specifically define ``variable''.  The preceding  sentences
  say  that it is an ``entity'' that has a name.  Probably a variable is
  ``a declared object that has a name''.
  +-------                  END BOX 1                 -------+

5 Every name that denotes an entity  is  introduced  by  a  declaration.
  Every  name that denotes a label is introduced either by a goto state­
  ment (_stmt.goto_) or a labeled-statement (_stmt.label_).  Every  name
  is  introduced  in  some  contiguous  portion of program text called a
  declarative region (_basic.scope_), which is the largest part  of  the
  program  in  which  that name can possibly be valid.  In general, each
  particular name is valid only within some possibly discontiguous  por­
  tion  of  program text called its scope (_basic.scope_).  To determine
  the scope of a declaration, it is sometimes convenient to refer to the
  potential  scope  of a declaration.  The scope of a declaration is the
  same as its  potential  scope  unless  the  potential  scope  contains
  another  declaration  of  the  same name.  In that case, the potential
  scope of the declaration in the inner (contained)  declarative  region
  is  excluded  from the scope of the declaration in the outer (contain­
  ing) declarative region.

6 [Example: in
          int j = 24;

          int main()
          {
                  int i = j, j;

                  j = 42;
          }
  the identifier j is declared twice as a name (and  used  twice).   The
  declarative  region  of  the first j includes the entire example.  The
  potential scope of the first j begins immediately  after  that  j  and
  extends to the end of the program, but its (actual) scope excludes the
  text between the , and the }.  The declarative region  of  the  second
  declaration of j (the j immediately before the semicolon) includes all
  the text between { and }, but its potential scope excludes the  decla­
  ration  of i.  The scope of the second declaration of j is the same as
  its potential scope.  ]

7 Some names denote types, classes, enumerations, or templates.  In gen­
  eral,  it  is necessary to determine whether or not a name denotes one
  of these entities before parsing the program that  contains  it.   The
  process that determines this is called name lookup (_class.scope_).

8 Two names denote the same entity if

  --they are identifiers composed of the same character sequence; or

  --they  are the names of overloaded operator functions formed with the
    same operator; or

  --they are the names of user-defined conversion functions formed  with
    the same type.

9 An  identifier  used in more than one translation unit can potentially
  refer to the same entity in these translation units depending  on  the
  linkage (_basic.link_) specified in the translation units.

  3.1  Declarations and definitions                          [basic.def]

1 A  declaration (_dcl.dcl_) introduces one or more names into a program
  and gives each name a meaning.

2 A declaration is a definition unless it declares  a  function  without
  specifying the function's body (_dcl.fct.def_), it contains the extern
  specifier (_dcl.stc_) and neither an initializer nor a  function-body,
  it   declares   a   static   data   member   in  a  class  declaration
  (_class.static_), it is a class name declaration (_class.name_), or it
  is   a   typedef   declaration   (_dcl.typedef_),   a  using  declara­
  tion(_namespace.udecl_), or a using directive(_namespace.udir_).

3 [Example: all but one of the following are definitions:

          int a;                       // defines a
          extern const int c = 1;      // defines c
          int f(int x) { return x+a; } // defines f
          struct S { int a; int b; };  // defines S
          struct X {                   // defines X
              int x;                   // defines nonstatic data member x
              static int y;            // declares static data member y
              X(): x(0) { }            // defines a constructor of X
          };
          int X::y = 1;                // defines X::y
          enum { up, down };           // defines up and down
          namespace N { int d; }       // defines N and N::d
          namespace N1 = N;            // defines N1
          X anX;                       // defines anX
  whereas these are just declarations:
          extern int a;                // declares a
          extern const int c;          // declares c
          int f(int);                  // declares f
          struct S;                    // declares S
          typedef int Int;             // declares Int
          extern X anotherX;           // declares anotherX
          using N::d;                  // declares N::d
   --end example]

4 [Note: in some circumstances, C++  implementations  implicitly  define
  the    default    constructor    (_class.ctor_),    copy   constructor
  (_class.copy_),  assignment  operator  (_class.copy_),  or  destructor
  (_class.dtor_) member functions.  [Example: given
          struct C {
              string s;    // string is the standard library class (_lib.string_)
          };

          int main()
          {
              C a;
              C b = a;
              b = a;
          }
  the  implementation will implicitly define functions to make the defi­
  nition of C equivalent to
          struct C {
              string s;
              C(): s() { }
              C(const C& x): s(x.s) { }
              C& operator=(const C& x) { s = x.s; return *this; }
              ~C() { }
          };
   --end example]  --end note]

5 [Note: a class name can also be implicitly declared by an  elaborated-
  type-specifier (_dcl.type.elab_).  ]

  3.2  One definition rule                               [basic.def.odr]

  +-------                 BEGIN BOX 2                -------+
  This is still very much under review by the Committee.
  +-------                  END BOX 2                 -------+

1 No  translation  unit  shall  contain  more than one definition of any
  variable, function, class type, enumeration type or template.

2 A function is used if it is called, its address is taken, or it  is  a
  virtual  member  function  that is not pure (_class.abstract_).  Every
  program shall contain at least one definition of every  function  that
  is used in that program.  That definition can appear explicitly in the
  program, it can be found in the standard or a user-defined library, or
  (when   appropriate)  it  is  implicitly  defined  (see  _class.ctor_,
  _class.dtor_ and _class.copy_).  If  a  non-virtual  function  is  not
  defined,  a diagnostic is required only if an attempt is actually made
  to call that function.  If a virtual function is  neither  called  nor
  defined, no diagnostic is required.

  +-------                 BEGIN BOX 3                -------+
  This   says   nothing   about  user-defined  libraries.   Probably  it
  shouldn't, but perhaps it should be more explicit that it  isn't  dis­
  cussing it.
  +-------                  END BOX 3                 -------+

3 A  non-local  variable with static storage duration shall have exactly
  one definition in a program unless the variable has a builtin type  or
  is  an aggregate and also is unused or used only as the operand of the
  sizeof operator.

  +-------                 BEGIN BOX 4                -------+
  This is still uncertain.
  +-------                  END BOX 4                 -------+

4 At least one definition of a class is required in a  translation  unit
  if  the class is used other than in the formation of a pointer or ref­
  erence type.

  +-------                 BEGIN BOX 5                -------+
  This is not quite right, because it is possible to declare a  function
  that  has  an  undefined class type as its return type, that has argu­
  ments of undefined class type.
  +-------                  END BOX 5                 -------+

  +-------                 BEGIN BOX 6                -------+
  There might be other situations that do not  require  a  class  to  be
  defined:  extern  declarations  (i.e.  "extern  X x;"), declaration of
  static members, others???

  +-------                  END BOX 6                 -------+

5 [Example: the following complete translation unit is well-formed, even
  though it never defines X:
          struct X;      // declare X is a struct type
          struct X* x1;  // use X in pointer formation
          X* x2;         // use X in pointer formation
   --end example]

6 There can be more than one definition of a named enumeration type in a
  program provided that each definition appears in a different  transla­
  tion unit and the names and values of the enumerators are the same.

  +-------                 BEGIN BOX 7                -------+
  This will need to be revisited when the ODR is made more precise
  +-------                  END BOX 7                 -------+

7 There  can  be  more  than one definition of a class type in a program
  provided that each definition appears in a different translation  unit
  and the definitions describe the same type.

8 No diagnostic is required for a violation of the ODR rule.

  +-------                 BEGIN BOX 8                -------+
  This will need to be revisited when the ODR is made more precise
  +-------                  END BOX 8                 -------+

  3.3  Declarative regions and scopes                      [basic.scope]

1 The name look up rules are summarized in _class.scope_.

  3.3.1  Local scope                                 [basic.scope.local]

1 A name declared in a block (_stmt.block_) is local to that block.  Its
  scope begins at its point  of  declaration  (_basic.scope.pdecl_)  and
  ends at the end of its declarative region.

2 A  function parameter name in a function definition (_dcl.fct.def_) is
  a local name in the scope of the outermost block of the  function  and
  shall not be redeclared in that scope.

3 The  name in a catch exception-declaration is local to the handler and
  shall not be redeclared in the outermost block of the handler.

4 Names declared in the for-init-statement, condition,  and  controlling
  expression  parts of if, while, for, and switch statments are local to
  the if, while, for, or  switch  statement  (including  the  controlled
  statement),  and  shall not be redeclared in a subsequent condition or
  controlling expression of that statement nor in the outermost block of
  the controlled statement.

5 Names declared in the outermost block of the controlled statement of a
  do statement shall not be redeclared in the controlling expression.

  3.3.2  Function prototype scope                    [basic.scope.proto]

1 In a function declaration, or in any of function declarator except the
  declarator  of a function definition (_dcl.fct.def_), names of parame­
  ters (if supplied) have function prototype scope, which terminates  at
  the end of the function declarator.

  3.3.3  Function scope

1 Labels  (_stmt.label_)  can  be used anywhere in the function in which
  they are declared.  Only labels have function scope.

  3.3.4  Namespace scope                         [basic.scope.namespace]

1 A name declared in a named or  unnamed  namespace  (_basic.namespace_)
  has  namespace scope.  Its potential scope includes its namespace from
  the name's point of declaration (_basic.scope.pdecl_) onwards, as well
  as  the potential scope of any using directive (_namespace.udir_) that
  nominates its namespace.  A namespace member can also  be  used  after
  the  :: scope resolution operator (_expr.prim_) applied to the name of
  its namespace.

2 A  name   declared   outside   all   named   or   unnamed   namespaces
  (_basic.namespace_),  blocks  (_stmt.block_) and classes (_class_) has
  global namespace scope (also  called  global  scope).   The  potential
  scope   of   such   a   name   begins  at  its  point  of  declaration
  (_basic.scope.pdecl_) and ends at the end of the translation unit that
  is  its  declarative  region.   Names declared in the global namespace
  scope are said to be global.

  3.3.5  Class scope                                 [basic.scope.class]

1 The name of a class member is local to its class and can be used  only
  in:

  --the  scope  of  that  class  (_class.scope0_)  or  a  class  derived
    (_class.derived_) from that class,

  --after the . operator applied to an expression of  the  type  of  its
    class (_expr.ref_) or a class derived from its class,

  --after the -> operator applied to a pointer to an object of its class
    (_expr.ref_) or a class derived from its class,

  --after the :: scope resolution operator (_expr.prim_) applied to  the
    name of its class or a class derived from its class,

  --or after a using declaration (_namespace.udecl_).

2 [Note:  The  scope  of  names  introduced  by  friend  declarations is
  described  in  _namespace.def_.   The  scope  rules  for  classes  are

  summarized in _class.scope0_.  ]

  3.3.6  Name hiding                                [basic.scope.hiding]

1 A name can be hidden by an explicit declaration of that same name in a
  nested declarative region or derived class.

2 A class name (_class.name_) or enumeration name  (_dcl.enum_)  can  be
  hidden  by  the name of an object, function, or enumerator declared in
  the same scope.  If a class or enumeration name and an  object,  func­
  tion, or enumerator are declared in the same scope (in any order) with
  the same name, the class or enumeration name is  hidden  wherever  the
  object, function, or enumerator name is visible.

3 In a member function definition, the declaration of a local name hides
  the declaration of a member of the  class  with  the  same  name;  see
  _class.scope0_.   The  declaration  of  a  member  in  a derived class
  (_class.derived_) hides the declaration of a member of a base class of
  the same name; see _class.member.lookup_.

4 If a name is in scope and is not hidden it is said to be visible.

  3.3.7  Explicit qualification                     [basic.scope.exqual]

  +-------                 BEGIN BOX 9                -------+
  The information in this section is very similar to the one provided in
  _namespace.qual_.    The   information   in   these    two    sections
  (_basic.scope.exqual_  and _namespace.qual_) should be consolidated in
  one place.
  +-------                  END BOX 9                 -------+

1 [Note: a name hidden by a nested declarative region or  derived  class
  can  still be used when it is qualified by its class or namespace name
  using the :: operator (_expr.prim_, _class.static_,  _class.derived_).
  A  hidden  global scope name can still be used when it is qualified by
  the unary :: operator (_expr.prim_).   --end note]

  3.3.8  Elaborated type specifier                    [basic.scope.elab]

1 A class name or enumeration name can be  hidden  by  the  name  of  an
  object, function, or enumerator in local, class or namespace scope.  A
  hidden class name can still be used when appropriately  prefixed  with
  class, struct, or union (_dcl.type_), or when followed by the :: oper­
  ator.  A hidden enumeration name can still be used when  appropriately
  prefixed with enum (_dcl.type_).  [Example:

          class A {
          public:
              static int n;
          };

          int main()
          {
              int A;

              A::n = 42;          // OK
              class A a;          // OK
              A b;                // ill-formed: A does not name a type
          }
   --end example]

2 [Note:  the  scope of class names first introduced in elaborated-type-
  specifiers is described in (_dcl.type.elab_).  ]

  3.3.9  Point of declaration                        [basic.scope.pdecl]

1 The point of declaration for a name is immediately after its  complete
  declarator (_dcl.decl_) and before its initializer (if any), except as
  noted below.  [Example:
      int x = 12;
      { int x = x; }
  Here the second x is initialized with its own (unspecified) value.  ]

2 A nonlocal name remains visible up to the point of declaration of  the
  local name that hides it.  [Example:
      const int  i = 2;
      { int  i[i]; }
  declares a local array of two integers.  ]

3 [Note: for the point of declaration for an enumerator, see _dcl.enum_.
  For the point of declaration of a function first declared in a  friend
  declaration,  see  _class.friend_.   For the point of declaration of a
  class first declared in an elaborated-type-specifier or  in  a  friend
  declaration,  see  _dcl.type.elab_.   For  point of instantiation of a
  template, see _temp.inst_.  ]

4
  3.4  Name look up                                        [class.scope]

1 The name look up rules apply uniformly to all names  (including  type­
  def-names  (_dcl.typedef_),  namespace-names  (_basic.namespace_)  and
  class-names (_class.name_)) wherever the grammar allows such names  in
  the  context  discussed  by a particular rule.  This section discusses
  name look up in lexical scope  only;  _basic.link_  discusses  linkage
  issues.   The notions of name hiding and point of declaration are dis­
  cussed in _basic.scope_.

2 Name look up associates the use of a name with a  visible  declaration
  (_basic.def_)  of  that  name.  Name look up shall find an unambiguous

  declaration for the name (see _class.member.lookup_).   Name  look  up
  may  associate  more  than one declaration with a name if it finds the
  name to be a function name; in this case, all the  declarations  shall
  be  found  in the same scope (_class.member.lookup_); the declarations
  are said to form a set of overloaded functions  (_over.load_).   Over­
  load resolution (_over.match_) takes place after name look up has suc­
  ceeded.  The access rules (_class.access_) are  considered  only  once
  name  look  up  and  function overload resolution (if applicable) have
  succeeded.  Only after name look up, function overload resolution  (if
  applicable)  and  access  checking  have  succeeded are the attributes
  introduced by the name's declaration used further in  expression  pro­
  cessing (_expr_).

3 A  name  used  in  the  global scope outside of any function, class or
  user-declared namespace, shall be declared before it is used in global
  scope  or be a name introduced by a using directive (_namespace.udir_)
  that appears in global scope before the name is used.

4 A name specified after a nested-name-specifier is  looked  up  in  the
  scope  of the class or namespace denoted by the nested-name-specifier;
  see _expr.prim_ and _namespace.qual_.  A name prefixed  by  the  unary
  scope  operator :: (_expr.prim_) is looked up in global scope.  A name
  specified after the . operator or -> operator of a class member access
  is looked up as specified in _expr.ref_.

5 A  name  that  is not qualified in any of the ways described above and
  that is used in a namespace outside of the definition of any  function
  or  class shall be declared before its use in that namespace or in one
  of its enclosing namespaces or, be introduced  by  a  using  directive
  (_namespace.udir_) visible at the point the name is used.

6 A  name  that  is not qualified in any of the ways described above and
  that is used in a function  that  is  not  a  class  member  shall  be
  declared  before its use in the block in which it is used or in one of
  its enclosing blocks (_stmt.block_) or, shall be declared  before  its
  use  in  the  namespace enclosing the function definition or in one of
  its enclosing namespaces or, shall be introduced by a using  directive
  (_namespace.udir_) visible at the point the name is used.

7 A  name  that  is not qualified in any of the ways described above and
  that is used in the definition of a class X outside of any inline mem­
  ber  function  or nested class definition shall be declared before its
  use in class X (_class.scope0_) or be a member  of  a  base  class  of
  class  X  (_class.derived_)  or,  if  X  is  a nested class of class Y
  (_class.nest_), shall be declared before the definition of class X  in
  the  enclosing class Y or in Y's enclosing classes or, if X is a local
  class (_class.local_), shall be  declared  before  the  definition  of
  class  X  in  a block enclosing the definition of class X or, shall be
  declared before the definition of class X in a namespace enclosing the
  definition  of class X or, be introduced by a using directive (_names­
  pace.udir_) visible at the point the name is used.   [Note:  Subclause
  _class.scope0_  further describes the restrictions on the use of names
  in a class definition.  Subclause _class.nest_ further  describes  the
  restrictions  on  the  use  of  names  in  nested  class  definitions.

  Subclause _class.local_ further describes the restrictions on the  use
  of names in local class definitions.  ]

8 A  name  that  is not qualified in any of the ways described above and
  that is used in a function that is a member function (_class.mfct_) of
  class  X  shall be declared before its use in the block in which it is
  used or in an enclosing block (_stmt.block_) or, shall be a member  of
  class  X  (_class.mem_)  or  a  member  of  a  base  class  of class X
  (_class.derived_)  or,  if  X  is  a   nested   class   of   class   Y
  (_class.nest_), shall be a member of the enclosing class Y or a member
  of Y's enclosing classes or, if X is a  local  class  (_class.local_),
  shall  be declared before the definition of class X in a block enclos­
  ing the definition of class X or, shall be declared before the  member
  function definition in a namespace enclosing the member function defi­
  nition or, be introduced by a using directive (_namespace.udir_) visi­
  ble  at the point the name is used.  [Note: Subclause _class.mfct_ and
  _class.static_ further describe the restrictions on the use  of  names
  in   member  function  definitions.   Subclause  _class.nest_  further
  describes the restrictions on the use of names in the scope of  nested
  classes.   Subclause  _class.local_ further describes the restrictions
  on the use of names in local class definitions.  ]

9 For a friend function (_class.friend_) defined inline in  the  defini­
  tion  of  the  class  granting  friendship, name look up in the friend
  function definition for a name that is not qualified  in  any  of  the
  ways  described above proceeds as described in member function defini­
  tions.  If the friend function is not defined in  the  class  granting
  friendship,  name look up in the friend function definition for a name
  that is not qualified in any of the ways described above  proceeds  as
  described in nonmember function definitions.

10A  name  that  is not qualified in any of the ways described above and
  that is used in a function parameter-declaration-clause as  a  default
  argument  (_dcl.fct.default_)  or  that  is  used  in a function ctor-
  initializer (_class.base.init_) is looked up as if the name  was  used
  in the outermost block of the function definition.  In particular, the
  function parameter names are visible for name look up in default argu­
  ments  and  in  ctor-initializers.  [Note: Subclause _dcl.fct.default_
  further describes the restrictions on the  use  of  names  in  default
  arguments.  Subclause _class.base.init_ further describes the restric­
  tions on the use of names in a ctor-initializer.  ]

11A name that is not qualified in any of the ways  described  above  and
  that is used in the initializer expression of a static member of class
  X (_class.static.data_) shall be a member of class X (_class.mem_)  or
  a  member  of  a base class of class X (_class.derived_) or, if X is a
  nested class of class Y (_class.nest_),  shall  be  a  member  of  the
  enclosing class Y or a member of Y's enclosing classes or, be declared
  before the static member definition in  the  namespace  enclosing  the
  static  member definition or in one of its enclosing namespaces or, be
  introduced by a using  directive  (_namespace.udir_)  visible  at  the
  point  the name is used.  [Note: Subclause _class.static.data_ further
  describes the restrictions on the use  of  names  in  the  initializer
  expression  for  a static data member.  Subclause _class.nest_ further

  describes the restrictions on the use of names in nested class defini­
  tions.  ]

12In  all  cases, the scopes are searched for a declaration in the order
  listed in each of the respective category above and name look up  ends
  as soon as a declaration is found for the name.

  +-------                BEGIN BOX 10                -------+
  This subclause should probably say something about look up in template
  definitions.
  +-------                 END BOX 10                 -------+

  3.5  Program and linkage                                  [basic.link]

1 A program consists of one or more  translation  units  (_lex_)  linked
  together.   A translation unit consists of a sequence of declarations.
          translation unit:
                  declaration-seqopt

2 A name is said to have linkage when it might denote the  same  object,
  function,  type, template, or value as a name introduced by a declara­
  tion in another scope:

  --When a name has external linkage,  the  entity  it  denotes  can  be
    referred  to by names from scopes of other translation units or from
    other scopes of the same translation unit.

  --When a name has internal linkage,  the  entity  it  denotes  can  be
    referred to by names from other scopes of the same translation unit.

  --When a name has no linkage, the entity it denotes cannot be referred
    to by names from other scopes.

3 A name of namespace scope (_basic.scope.namespace_) has internal link­
  age if it is the name of

  --a variable that is explicitly  declared  static  or,  is  explicitly
    declared const and neither explicitly declared extern nor previously
    declared to have external linkage; or

  --a function that is explicitly  declared  static  or,  is  explicitly
    declared  inline  and  neither explicitly declared extern nor previ­
    ously declared to have external linkage; or

  --the name of a data member of an anonymous union.

4 A name of namespace scope has external linkage if it is the name of

  --a variable, unless it has internal linkage; or

  --a function, unless it has internal linkage; or

  --a class (_class_) or enumeration (_dcl.enum_) or an enumerator; or

  --a template (_temp_).

5 In addition, a name of class scope has external linkage if the name of
  the class has external linkage.

6 The  name  of  a  function  declared  in  a  block scope or a variable
  declared extern in a block  scope  has  linkage,  either  internal  or
  external  to  match  the  linkage of prior visible declarations of the
  name in the same translation unit, but if there is  no  prior  visible
  declaration it has external linkage.

7 Names not covered by these rules have no linkage.  Moreover, except as
  noted, a name declared in a local scope (_basic.scope.local_)  has  no
  linkage.  A name with no linkage (notably, the name of a class or enu­
  meration declared in a local scope (_basic.scope.local_)) shall not be
  used to declare an entity with linkage.  [Example:
          void f()
          {
              struct A { int x; };       // no linkage
              extern A a;                // ill-formed
          }
   --end example] This implies that names with no linkage cannot be used
  as template arguments (_temp.arg_).

8 Two names that are the same and that are declared in different  scopes
  shall  denote the same object, function, type, enumerator, or template
  if

  --both names have external linkage or else both  names  have  internal
    linkage and are declared in the same translation unit; and

  --both names refer to members of the same namespace or to members, not
    by inheritance, of the same class; and

  --when both names denote functions or function templates, the function
    types are identical for purposes of overloading.

9 After  all adjustments of types (during which typedefs (_dcl.typedef_)
  are replaced by their definitions), the types specified by all  decla­
  rations  of a particular external name shall be identical, except that
  declarations for an array object can specify array types  that  differ
  by  the  presence or absence of a major array bound (_dcl.array_), and
  declarations for functions with the same name  can  specify  different
  numbers and types of parameters (_dcl.fct_).  A violation of this rule
  on type identity does not require a diagnostic.

10[Note: linkage to non-C++ declarations can be achieved using  a  link­
  age-specification (_dcl.link_).  ]

  3.6  Start and termination                               [basic.start]

  3.6.1  Main function                                [basic.start.main]

1 A  program  shall  contain a global function called main, which is the
  designated start of the program.

  +-------                BEGIN BOX 11                -------+
  In C, a freestanding environment does not require  main;  the  program
  invocation  method  is implementation-defined.  Should C++?  [Yes, C++
  should require main - because unlike in C, this C++  standard  defines
  the semantics of program start and termination.  This was done so that
  freestanding environments can get the same  level  of  definition  for
  order of static constructors/destructors.  --Neal Gafter]
  +-------                 END BOX 11                 -------+

2 This  function  is  not predefined by the implementation, it cannot be
  overloaded, and its type is implementation-defined.   All  implementa­
  tions shall allow both of the following definitions of main:
          int main() { /* ... */ }
  and
          int main(int argc, char* argv[]) { /* ... */ }
  In the latter form argc shall be the number of arguments passed to the
  program from the environment in which the program is run.  If argc  is
  nonzero   these   arguments  shall  be  supplied  in  argv[0]  through
  argv[argc-1] as pointers to the initial characters of  null-terminated
  multibyte  strings  (NTMBSs)  and  argv[0] shall be the pointer to the
  initial character of a NTMBS that represents the name used  to  invoke
  the program or "".  The value of argc shall be nonnegative.  The value
  of argv[argc] shall be 0.  [Note: It is recommended that  any  further
  (optional) parameters be added after argv.  ]

3 The  function  main()  shall not be called from within a program.  The
  linkage  (_basic.link_)  of  main()  is  implementation-defined.   The
  address  of main() shall not be taken and main() shall not be declared
  inline or static.  The name main is not otherwise reserved.  [Example:
  member functions, classes, and enumerations can be called main, as can
  entities in other namespaces.  ]

4 Calling the function
          void exit(int);
  declared in <cstdlib> (_lib.support.start.term_) terminates  the  pro­
  gram  without  leaving  the current block and hence without destroying
  any objects with automatic storage duration (_class.dtor_).  The argu­
  ment  value  is  returned to the program's environment as the value of
  the program.

  +-------                BEGIN BOX 12                -------+
  Several members of the Core  editing  group  question  this.   Can  we
  require  that  exit  destroy  automatic-duration  objects?  Or make it
  implementation-defined whether the unwinding  occurs?   If  an  imple­
  menter's  market  _wants_  exit  to  unwind,  and  the implementer can

  provide the necessary stack-unwinding, why should  the  Standard  pro­
  hibit  it?   For  an immediate ``get me out of here'', there is always
  the abort function.  The footnote in _lib.exit_ claims that an unwind­
  ing  can  be achieved by throwing an exception that is caught in main,
  but this assumes and requires that no  handlers  for  ...   intervene.
  There  appears  to  be  no way of exiting via exception that cannot be
  intercepted by such handlers.
  +-------                 END BOX 12                 -------+

5 A return statement in main() has the effect of leaving the main  func­
  tion  (destroying  any  objects  with  automatic storage duration) and
  calling exit() with the return value  as  the  argument.   If  control
  reaches  the  end of main without encountering a return statement, the
  effect is that of executing
          return 0;

  3.6.2  Initialization of non-local objects          [basic.start.init]

1 The initialization of nonlocal objects with  static  storage  duration
  (_basic.stc_)  defined  in a translation unit is done before the first
  use of any function or object defined in that translation unit.   Such
  initializations     (_dcl.init_,     _class.static_,     _class.ctor_,
  _class.expl.init_) can be done before the first statement of main() or
  deferred  to  any  point in time before the first use of a function or
  object defined in that translation unit.  The storage for objects with
  static  storage  duration  is zero-initialized (_dcl.init_) before any
  other initialization takes place.  Objects with static  storage  dura­
  tion initialized with constant expressions (_expr.const_) are initial­
  ized before any  dynamic  (that  is,  run-time)  initialization  takes
  place.   The  order  of initialization of nonlocal objects with static
  storage duration defined in the same translation unit is the order  in
  which  their  definition appears in this translation unit.  No further
  order is imposed on  the  initialization  of  objects  from  different
  translation  units.   The  initialization  of  local static objects is
  described in _stmt.dcl_.

2 If construction or destruction of a non-local static  object  ends  in
  throwing  an  uncaught  exception,  the  result is to call terminate()
  (_lib.terminate_).

  3.6.3  Termination                                  [basic.start.term]

1 Destructors (_class.dtor_) for initialized static objects  are  called
  when    returning    from    main()    and    when    calling   exit()
  (_lib.support.start.term_).  Destruction is done in reverse  order  of
  initialization.   The  function atexit() from <cstdlib> can be used to
  specify a function to be called at exit.  If atexit() is to be called,
  the  implementation  shall  not  destroy objects initialized before an
  atexit() call until after the function specified in the atexit()  call
  has been called.

2 Where  a  C++  implementation  coexists  with  a C implementation, any
  actions specified by the C implementation  to  take  place  after  the

  atexit()  functions  have been called take place after all destructors
  have been called.

3 Calling the function
          void abort();
  declared  in  <cstdlib>  terminates  the  program  without   executing
  destructors  for  static  objects  and  without  calling the functions
  passed to atexit().

  3.7  Storage duration                                      [basic.stc]

1 Storage duration is a property of an object that indicates the  poten­
  tial  time  extent the storage in which the object resides might last.
  The storage duration is determined by the construct used to create the
  object and is one of the following:

  --static storage duration

  --automatic storage duration

  --dynamic storage duration

2 Static  and  automatic  storage  durations are associated with objects
  introduced by declarations (_basic.def_).  The dynamic  storage  dura­
  tion   is   associated   with   objects   created  with  operator  new
  (_expr.new_).

3 The storage class specifiers static, auto, and mutable are related  to
  storage duration as described below.

4 References  (_dcl.ref_)  might  or might not require storage; however,
  the storage duration categories apply to references as well.

  3.7.1  Static storage duration                      [basic.stc.static]

1 All non-local objects have static storage duration.  The  storage  for
  these  objects can last for the entire duration of the program.  These
  objects   are   initialized   and   destroyed    as    described    in
  _basic.start.init_ and _basic.start.term_.

2 Note  that  if an object of static storage duration has initialization
  or a destructor with side effects, it shall not be eliminated even  if
  it appears to be unused.

  +-------                BEGIN BOX 13                -------+
  This awaits committee action on the ``as-if'' rule.
  +-------                 END BOX 13                 -------+

3 The keyword static can be used to declare a local variable with static
  storage duration; for a description of initialization and  destruction
  of local static variables, see _stmt.dcl_.

4 The  keyword  static applied to a class data member in a class defini­
  tion gives the data member static storage duration.

  3.7.2  Automatic storage duration                     [basic.stc.auto]

1 Local objects explicitly declared auto or register or  not  explicitly
  declared  static  have  automatic  storage  duration.  The storage for
  these objects lasts until the block in which they are created exits.

2 [Note: These  objects  are  initialized  and  destroyed  as  described
  _stmt.dcl_.  ]

3 If  a  named  automatic object has initialization or a destructor with
  side effects, it shall not be destroyed before the end of  its  block,
  nor shall it be eliminated as an optimization even if it appears to be
  unused.

  3.7.3  Dynamic storage duration                    [basic.stc.dynamic]

1 Objects  can  be  created   dynamically   during   program   execution
  (_intro.execution_), using new-expressions (_expr.new_), and destroyed
  using delete-expressions (_expr.delete_).  A C++  implementation  pro­
  vides  access  to,  and  management of, dynamic storage via the global
  allocation functions operator new and operator new[]  and  the  global
  deallocation functions operator delete and operator delete[].

2 These  functions are always implicitly declared.  The library provides
  default definitions for them (_lib.new.delete_).  A C++ program  shall
  provide  at  most  one  definition  of any of the functions ::operator
  new(size_t),  ::operator  new[](size_t),   ::operator   delete(void*),
  and/or  ::operator  delete[](void*).   Any  such  function definitions
  replace the default versions.  This replacement is  global  and  takes
  effect  upon program startup (_basic.start_).  Allocation and/or deal­
  location functions can also be declared  and  defined  for  any  class
  (_class.free_).

3 Any  allocation and/or deallocation functions defined in a C++ program
  shall conform to the semantics specified in this subclause.

  3.7.3.1  Allocation functions           [basic.stc.dynamic.allocation]

1 Allocation functions can be static class member  functions  or  global
  functions.   They  can be overloaded, but the return type shall always
  be  void*  and  the  first  parameter  type  shall  always  be  size_t
  (_expr.sizeof_),  an  implementation-defined  integral type defined in
  the standard header  <cstddef>  (_lib.language.support_).   For  these
  functions, parameters other than the first can have associated default
  arguments (_dcl.fct.default_).

2 The function shall return the address of a block of available  storage
  at  least  as large as the requested size.  The order, contiguity, and
  initial value of storage allocated by successive calls to  an  alloca­
  tion  function  is  unspecified.   The  pointer  returned  is suitably

  aligned so that it can be assigned to a pointer of any type  and  then
  used to access such an object or an array of such objects in the stor­
  age allocated (until the storage is explicitly deallocated by  a  call
  to a corresponding deallocation function).  Each such allocation shall
  yield a pointer to storage (_intro.memory_) disjoint  from  any  other
  currently allocated storage.  The pointer returned points to the start
  (lowest byte address) of the allocated storage.  If the  size  of  the
  space requested is zero, the value returned shall be nonzero and shall
  not pointer to or within any other currently allocated  storage.   The
  results of dereferencing a pointer returned as a request for zero size
  are undefined.1)

3 If  an allocation function is unable to obtain an appropriate block of
  storage, it can invoke  the currently installed  new_handler2)  and/or
  throw  an exception (_except_) of class bad_alloc (_lib.bad.alloc_) or
  a class derived from bad_alloc.

4 If the allocation function returns the  null  pointer  the  result  is
  implementation-defined.

  3.7.3.2  Deallocation functions       [basic.stc.dynamic.deallocation]

1 Like  allocation functions, deallocation functions can be static class
  member functions or global functions.

2 Each deallocation function shall return void and its  first  parameter
  shall  be  void*.   For  class member deallocation functions, a second
  parameter of type size_t may be added. If both versions  are  declared
  in  the  same  class, the one-parameter form is the usual deallocation
  function and the two-parameter  form  is  used  for  placement  delete
  (_expr.new_).  If the second version is declared but not the first, it
  is the usual deallocation function, not placement delete.

3 The value of the first parameter supplied to a  deallocation  function
  shall  be  zero,  or  refer  to storage allocated by the corresponding
  allocation function (even if that allocation function was called  with
  a  zero  argument).   If  the value of the first argument is zero, the
  call to the deallocation function has no effect.  If the value of  the
  first  argument refers to a pointer already deallocated, the effect is
  undefined.

4 A deallocation function can free the storage referenced by the pointer
  given  as  its  argument and renders the pointer invalid.  The storage
  can be made available for further allocation.  An invalid pointer con­
  tains an unusable value:  it cannot even be used in an expression.
  _________________________
  1) The intent is to have operator new() implementable by calling  mal­
  loc()  or calloc(), so the rules are substantially the same.  C++ dif­
  fers from C in requiring a zero request to return a non-null  pointer.
  2) A program-supplied allocation function can obtain  the  address  of
  the  currently  installed  new_handler  (_lib.new.handler_)  using the
  set_new_handler() function (_lib.set.new.handler_).

5 If  the  argument  is  non-zero, the value of a pointer that refers to
  deallocated space is indeterminate.  The effect  of  dereferencing  an
  indeterminate pointer value is undefined.3)

  3.7.4  Duration of sub-objects                     [basic.stc.inherit]

1 The storage duration of member subobjects, base class  subobjects  and
  array elements is that of their complete object (_intro.object_).

  3.8  Object Lifetime                                      [basic.life]

1 The  lifetime  of  an object is a runtime property of the object.  The
  lifetime of an object of type T begins when:

  --storage with the proper alignment and size for type T  is  obtained,
    and

  --if  T is a class type with a non-trivial constructor (_class.ctor_),
    the constructor call has completed.

  The lifetime of an object of type T ends when:

  --if T is a class type with a non-trivial  destructor  (_class.dtor_),
    the destructor call starts, or

  --the storage which the object occupies is reused or released.

2 [Note: The lifetime of an object of POD type starts as soon as storage
  with proper size and alignment is obtained, and its lifetime ends when
  the  storage  which  the  object occupies is reused or released.  Sub­
  clause _class.base.init_ describes the lifetime  of  base  and  member
  subobjects.  ]

  +-------                BEGIN BOX 14                -------+
  What is the lifetime of an array?  There are two options:

  --arrays  always  behave  like  PODs, their lifetime starts as soon as
    storage is allocated for the array and ends when the  storage  which
    the array occupies is reused or released, or

  --arrays  of  PODs  have  a lifetime that starts as soon as storage is
    allocated for the array and ends when the storage  which  the  array
    occupies  is  reused or released; arrays of classes with non-trivial
    constructors have a lifetime that starts when the  constructor  call
    for  the  last  element  has  completed; arrays of classes with non-
    trivial destructors have a lifetime that ends  when  the  destructor
    call for the first array element starts.

  +-------                 END BOX 14                 -------+
  _________________________
  3)  On some architectures, it causes a system-generated runtime fault.

3 The properties ascribed to objects throughout this International Stan­
  dard apply for a given object only during its lifetime.   In  particu­
  lar,  except  as  noted during object construction (_class.base.init_)
  and destruction (_class.cdtor_), before the  lifetime  of  the  object
  starts  and after its lifetime ends the value of the storage which the
  object occupies is indeterminate and, for an object of  non-POD  class
  type, referring to a non-static data member, calling a non-static mem­
  ber function or converting  the  object  to  a  base  class  subobject
  results in undefined behavior.

4 [Note:  The  behavior  of an object under construction and destruction
  might not be the same as the behavior of an object whose lifetime  has
  started and not ended.  Subclauses _class.base.init_ and _class.cdtor_
  describe the  behavior  of  an  object  during  the  construction  and
  destruction phases.  ]

5 A  program  may  end the lifetime of any object by reusing the storage
  which the object occupies or by explicitly calling the destructor  for
  an  object  of  a  class  type  with a non-trivial destructor.  For an
  object of a class type with a non-trivial destructor, the  program  is
  not  required  to  call  the  destructor explicitly before the storage
  which the object occupies is reused or released; however, if there  is
  no   explicit  call  to  the  destructor  or  if  a  delete-expression
  (_expr.delete_) is not used to release the storage, the destructor  is
  not implicitly called and any program that depends on the side effects
  produced by the destructor has unspecified behavior.

6 After the lifetime of an object has ended and while the storage  which
  the  object  occupied still exists, any pointer to the original object
  can be used but only in limited ways.  Such a pointer still points  to
  valid  storage and using the pointer as a pointer to the storage where
  the object was located, as if the pointer were of type void*, is well-
  defined.   However,  using the pointer to refer to the original object
  is no longer valid.  In particular, such a pointer cannot be  derefer­
  enced; for a non-POD class type T, a pointer of type T* that points to
  the  original  object  cannot  be  the  operand   of   a   static_cast
  (_expr.static.cast_) (except when the conversion is to void* or char*)
  and cannot be the operand of a dynamic_cast (_expr.dynamic.cast_);  if
  T  is  a class with a non-trivial destructor, such a pointer cannot be
  used as the operand of a delete-expression.  [Example:
          struct B {
                  virtual void f();
                  void mutate();
                  virtual ~B();
          };

          struct D1 : B { void f(); };
          struct D2 : B { void f(); };
          void B::mutate() {
                  new (this) D2;  // reuses storage - ends the lifetime of '*this'
                  f();            // undefined behavior
                  ... = this;     // ok, 'this' points to valid memory
          }

          void g() {
                  void* p = malloc(sizeof(D1) + sizeof(D2));
                  B* pb = new (p) D1;
                  pb->mutate();
                  &pb;            // ok: pb points to valid memory
                  void* q = pb;   // ok: pb points to valid memory
                  pb->f();        // undefined behavior, lifetime of *pb has ended
          }
   --end example]

7 If, after the lifetime of an object has ended and  while  the  storage
  which the object occupied still exists, a new object is created at the
  storage location which the original object occupied,  a  pointer  that
  pointed  to  the  original  object will automatically refer to the new
  object and, once the lifetime of the new object has  started,  can  be
  used to manipulate the new object, if:

  --the storage for the new object exactly overlays the storage location
    which the original object occupied, and

  --the new object is of the same type as the original object  (ignoring
    the top-level cv-qualifiers), and

  --the  original  object  was  a  complete object of type T and the new
    object is a complete object of type T (that is, they  are  not  base
    class subobjects).  [Example:
              struct C {
                      int i;
                      void f();
                      const C& operator=( const C& );
              };
              const C& C::operator=( const C& other)
              {
                      if ( this != &other )
                      {
                              this->~C();          // lifetime of '*this' ends
                              new (this) C(other); // new object of type C created
                              f();                 // well-defined
                      }
                      return *this;
              }
              C c1;
              C c2;
              c1 = c2; // well-defined
              c1.f();  // well-defined; c1 refers to a new object of type C
     --end example]

8 If  a  program  ends  the  lifetime of an object of type T with static
  (_basic.stc.static_) or automatic (_basic.stc.auto_) storage  duration
  and if T has a non-trivial destructor,4) the program must ensure  that
  _________________________
  4) that is, an object for which a destructor will be called implicitly
  -- either upon exit from the block for an object with automatic  stor­
  age  duration  or upon exit from the program for an object with static

  an  object  of  the  original type occupies that same storage location
  when the implicit destructor call takes place; otherwise the  behavior
  of the program is undefined.  This is true even if the block is exited
  with an exception.  [Example:
          struct B {
                  ~B();
          };
          void h() {
                  B b;
                  new (&b) T;
          } // undefined behavior at block exit
   --end example]

  +-------                BEGIN BOX 15                -------+
  const objects need special treatment.  A possible solution that  still
  needs work:

9 "The  storage  which  a  const object occupies may be write-protected.
  Creating a new object at the storage location  which  a  const  object
  occupies  or  at  the  storage  location  which a const object used to
  occupy before its  lifetime  ended  results  in  undefined  behavior."
  [Example:
          struct B {
                  ~B();
          };
          void h() {
                  const B b;
                  b.~B();
                  new (&b) B; // undefined behavior
          }
   --end example]
  +-------                 END BOX 15                 -------+

  3.9  Types                                               [basic.types]

1 This  clauses  imposes requirements on processors regarding the repre­
  sentation of types.  There are two kinds of types:  fundamental  types
  and  compound  types.  Types describe objects (_intro.object_), refer­
  ences (_dcl.ref_), or functions (_dcl.fct_).

2 For any object type T, the underlying bytes  (_intro.memory_)  of  the
  object   can   be   copied   (using   the   memcpy   library  function
  (_lib.headers_) into an array of char  or  unsigned  char.   The  copy
  operation  is  well-defined,  even if the object does not hold a valid
  value of type T.  Whether or not the value  of  the  object  is  later
  changed,  if  the  content  of  the  array of char or unsigned char is
  copied back into the object using the  memcpy  library  function,  the
  object shall subsequently hold its original value.  [Example:

  _________________________
  storage duration.

          #define N sizeof(T)
          char buf[N];
          T obj;  // obj initialized to its original value
          memcpy(buf, &obj, N);
                  // between these two calls to memcpy,
                  // obj might be modified
          memcpy(&obj, buf, N);
                  // at this point, each subobject of obj of scalar type
                  // holds its original value
   --end example]

3 For  any  scalar  type  T,  if  two  pointers to T point to distinct T
  objects obj1 and obj2, if the value of obj1 is copied into obj2, using
  the  memcpy  library  function,  obj2 shall subsequently hold the same
  value as obj1.  [Example:
          T* t1p;
          T* t2p;
                  // provided that t2p points to an initialized object ...
          memcpy(t1p, t2p, sizeof(T));
                  // at this point, every subobject of scalar type in *t1p
                  // contains the same value as the corresponding subobject in
                  // *t2p
   --end example]

4 The object representation of an object of type T is the sequence of  N
  unsigned char objects taken up by the object of type T, where N equals
  sizeof(T).  The value representation of an object is the  sequence  of
  bits  in the object representation that hold the value of type T.  The
  bits of the value representation determine a value, which is one  dis­
  crete element of an implementation-defined set of values.5)

5 Object  types  have   alignment   requirements   (_basic.fundamental_,
  _basic.compound_).   The alignment of an object type is an implementa­
  tion-defined integer value representing a number of bytes;  an  object
  is  allocated  at an address that is divisible by the alignment of its
  object type.

6 Arrays of unknown size and classes that have  been  declared  but  not
  defined are called incomplete types.6)  Also,  the  void  type  is  an
  incomplete  type;  it  represents  an empty set of values.  No objects
  shall be defined to have  incomplete  type.   The  term  incompletely-
  defined  object  type  is a synonym for incomplete type; the term com­
  pletely-defined object type is a synonym for complete type;

7 A class type (such as "class X") might be incomplete at one point in a
  translation unit and complete later on; the type "class X" is the same
  type at both points.  The declared type of an array  might  be  incom­
  plete  at  one  point in a translation unit and complete later on; the
  _________________________
  5)  The intent is that the memory model of C++ is compatible with that
  of ISO/IEC 9899 Programming Language C.
  6)  The  size  and  layout of an instance of an incomplete type is un­
  known.

  array types at those two points ("array of unknown  bound  of  T"  and
  "array  of  N T") are different types.  However, the type of a pointer
  to array of unknown size, or of a type defined by a  typedef  declara­
  tion to be an array of unknown size, cannot be completed.  [Example:
          class X;             // X is an incomplete type
          extern X* xp;        // xp is a pointer to an incomplete type
          extern int arr[];    // the type of arr is incomplete
          typedef int UNKA[];  // UNKA is an incomplete type
          UNKA* arrp;          // arrp is a pointer to an incomplete type
          UNKA** arrpp;
          void foo()
          {
              xp++;             // ill-formed:  X is incomplete
              arrp++;           // ill-formed:  incomplete type
              arrpp++;          // okay: sizeof UNKA* is known
          }
          struct X { int i; };  // now X is a complete type
          int  arr[10];         // now the type of arr is complete
          X x;
          void bar()
          {
              xp = &x;          // okay; type is ``pointer to X''
              arrp = &arr;      // ill-formed: different types
              xp++;             // okay:  X is complete
              arrp++;           // ill-formed:  UNKA can't be completed
          }
   --end example]

8 [Note: Clause _expr_, _stmt.stmt_ and _dcl.dcl_ describe in which con­
  texts incomplete types are prohibited.  ]

9 Arithmetic and enumeration  types  (_basic.fundamental_)  and  pointer
  types  (_basic.compound_)  are  scalar types.  Scalar types, POD class
  types, POD union types (_class_) and arrays  of  such  types  are  POD
  types.

10If  two  types T1 and T2 are the same type, then T1 and T2 are layout-
  compatible types.  [Note: Layout-compatible enumerations are described
  in  _dcl.enum_.   Layout-compatible  POD-structs  and  POD-unions  are
  described in _class.mem_.  ]

  3.9.1  Fundamental types                           [basic.fundamental]

1 There are several fundamental types.  Specializations of the  standard
  template   numeric_limits  (_lib.support.limits_)  shall  specify  the
  largest and smallest values of each for an implementation.

2 Objects declared as characters char) shall be large  enough  to  store
  any  member of the implementation's basic character set.  If a charac­
  ter from this set is stored in a character object, its value shall  be
  equivalent  to  the integer code of that character.  It is implementa­
  tion-defined whether a char object can take on negative values.  Char­
  acters  can  be  explicitly  declared unsigned or signed.  Plain char,
  signed char, and unsigned char are three distinct types.   A  char,  a

  signed char,  and  an  unsigned char occupy the same amount of storage
  and have the same alignment  requirements  (_basic.types_);  that  is,
  they  have  the  same object representation.  For character types, all
  bits of the object representation participate in the value representa­
  tion.  For  unsigned character types, all possible bit patterns of the
  value representation represent numbers. These requirements do not hold
  for  other  types.   In  any  particular  implementation, a plain char
  object can take on either the same  values  as  a  signed char  or  an
  unsigned char; which one is implementation-defined.

3 An enumeration comprises a set of named integer constant values, which
  form the basis for an integral subrange that  includes  those  values.
  Each  distinct  enumeration  constitutes  a different enumerated type.
  Each constant has the type of its enumeration.

4 There are four signed  integer  types:  "signed  char",  "short  int",
  "int",  and  "long  int." In this list, each type provides at least as
  much storage as those preceding it in the list, but the implementation
  can otherwise make any of them equal in storage size.  Plain ints have
  the natural size suggested by  the  machine  architecture;  the  other
  signed integer types are provided to meet special needs.

5 For  each  of  the  signed integer types, there exists a corresponding
  (but different) unsigned  integer  type:  "unsigned  char",  "unsigned
  short  int",  "unsigned  int",  and "unsigned long int," each of which
  occupies the same  amount  of  storage  and  has  the  same  alignment
  requirements  (_basic.types_)  as  the  corresponding  signed  integer
  type7)  ; that is, each signed integer type has the same object repre­
  sentation as its corresponding unsigned integer type.   The  range  of
  nonnegative  values of a signed integer type is a subrange of the cor­
  responding unsigned integer type, and the value representation of  the
  same value in each type shall be the same.

6 Unsigned  integers,  declared  unsigned, shall obey the laws of arith­
  metic modulo 2n where n is the number of bits in the representation of
  that particular size of integer.8)

7 Type  wchar_t  is  a distinct type whose values can represent distinct
  codes for all members of the largest extended character set  specified
  among  the  supported locales (_lib.locale_).  Type wchar_t shall have
  the same size, signedness, and alignment requirements (_intro.memory_)
  as one of the other integral types, called its underlying type.

8 Values of type bool are either true or false.9) There are  no  signed,
  _________________________
  7) See _dcl.type.simple_ regarding the  correspondence  between  types
  and the sequences of type-specifiers that designate them.
  8) This implies that unsigned arithmetic does not overflow.
  9) Using a bool value in ways described by this International Standard
  as ``undefined,'' such as by examining the value of  an  uninitialized
  automatic variable, might cause it to behave as if is neither true nor
  false.

  unsigned,  short,  or  long bool types or values.  As described below,
  bool values behave as integral types.  Values of type bool participate
  in integral promotions (_conv.prom_, _expr.type.conv_).  Although val­
  ues of type bool generally behave as signed integers, for  example  by
  promoting  (_conv.prom_)  to int instead of unsigned int, a bool value
  can successfully be stored in a bit-field of any (nonzero) size.

9 Types bool, char, wchar_t, and the signed and unsigned  integer  types
  are collectively called integral types.10) A synonym for integral type
  is integer type.  The representations of integral types  shall  define
  values by use of  a pure binary numeration system.

  +-------                     BEGIN BOX 16                     -------+
  Does  this  mean  two's  complement?   Is  there a definition of "pure
  binary numeration system?"
  +-------                      END BOX 16                      -------+

10There are three floating point types: float, double, and long  double.
  The  type double provides at least as much precision as float, and the
  type long double provides at least as much precision as double.

  +-------                     BEGIN BOX 17                     -------+
  Should this say ``at least as much range and precision?''  C does.
  +-------                      END BOX 17                      -------+

  The value representation of floating-point is  implementation-defined.
  Integral  and floating types are collectively called arithmetic types.

11The void type has an empty set of values.  It is used  as  the  return
  type  for  functions that do not return a value.  Objects of type void
  shall not be declared.  Any expression can be explicitly converted  to
  type  void  (_expr.cast_); the resulting expression shall be used only
  as an expression statement (_stmt.expr_), as the  left  operand  of  a
  comma expression (_expr.comma_), or as a second or third operand of ?:
  (_expr.cond_).

12[Note: Even if the implementation defines two or more basic  types  to
  have  the  same  value representation, they are nevertheless different
  types.  ]

  3.9.2  Compound types                                 [basic.compound]

1 There is a conceptually infinite number of compound types  constructed
  from the fundamental types in the following ways:

  --arrays of objects of a given type, _dcl.array_;

  _________________________
  10)  Therefore,  enumerations  (_dcl.enum_) are not integral; however,
  enumerations can be promoted to int, unsigned int, long,  or  unsigned
  long, as specified in _conv.prom_.

  --functions,  which  have parameters of given types and return void or
    references or objects of a given type, _dcl.fct_;

  --pointers to void or objects or functions (including  static  members
    of classes) of a given type, _dcl.ptr_;

  --references to objects or functions of a given type, _dcl.ref_;

  --constants, which are values of a given type, _dcl.type_;

  --classes containing a sequence of objects of various types (_class_),
    a set of functions for manipulating  these  objects  (_class.mfct_),
    and  a  set of restrictions on the access to these objects and func­
    tions, _class.access_;

  --unions, which are classes capable of containing objects of different
    types at different times, _class.union_;

  --pointers to non-static11) class members, which identify members of a
    given type within objects of a given class, _dcl.mptr_.

2 These  methods  of  constructing  types  can  be  applied recursively;
  restrictions are mentioned in _dcl.ptr_, _dcl.array_,  _dcl.fct_,  and
  _dcl.ref_.

3 A  pointer  to  objects  of type T is referred to as a "pointer to T."
  [Example: a pointer to an  object  of  type  int  is  referred  to  as
  "pointer  to  int"  and  a pointer to an object of class X is called a
  "pointer to X." ] Except for pointers to static members,  text  refer­
  ring to "pointers" does not apply to pointers to members.  Pointers to
  incomplete types are allowed although there are restrictions  on  what
  can  be  done  with them (_basic.types_).  The value representation of
  pointer types is implementation-defined.  Pointers to cv-qualified and
  cv-unqualified  versions (_basic.type.qualifier_) of layout-compatible
  types shall have the same value representation and alignment  require­
  ments (_basic.types_).

4 Objects  of  cv-qualified  (_basic.type.qualifier_)  or cv-unqualified
  type void* (pointer to void), can be  used  to  point  to  objects  of
  unknown  type.   A  void* shall be able to hold any object pointer.  A
  cv-qualified or cv-unqualified  (_basic.type.qualifier_)  void*  shall
  have  the  same  representation  and  alignment  requirements as a cv-
  qualified or cv-unqualified char*.

5 Except for pointers to static members, text  referring  to  "pointers"
  does not apply to pointers to members.

  _________________________
  11)  Static  class  members  are objects or functions, and pointers to
  them are ordinary pointers to objects or functions.

  3.9.3  CV-qualifiers                            [basic.type.qualifier]

1 A  type mentioned in _basic.fundamental_ and _basic.compound_ is a cv-
  unqualified    type.     Each    cv-unqualified    fundamental    type
  (_basic.fundamental_) has three corresponding cv-qualified versions of
  its type: a const-qualified version, a volatile-qualified version, and
  a    const-volatile-qualified   version.    The   term   object   type
  (_intro.object_) includes the cv-qualifiers specified when the  object
  is created.  The presence of a const specifier in a decl-specifier-seq
  declares an object of const-qualified  object  type;  such  object  is
  called  a  const  object.   The  presence of a volatile specifier in a
  decl-specifier-seq declares an  object  of  volatile-qualified  object
  type;  such  object is called a volatile object.  The presence of both
  cv-qualifiers in a decl-specifier-seq declares  an  object  of  const-
  volatile-qualified object type; such object is called a const volatile
  object.  The cv-qualified or cv-unqualified versions  of  a  type  are
  distinct  types;  however, they shall have the same representation and
  alignment requirements (_basic.types_).12)

2 A compound type (_basic.compound_) is  not  cv-qualified  by  the  cv-
  qualifiers (if any) of the type from which it is compounded.  However,
  any cv-qualifiers that appears in an array declaration  apply  to  the
  array element type, not the array type (_dcl.array_).

3 Each non-function, non-static, non-mutable member of a const-qualified
  class object is const-qualified, each non-function, non-static  member
  of  a  volatile-qualified class object is volatile-qualified and simi­
  larly for  members  of  a  const-volatile  class.  See  _dcl.fct_  and
  _class.this_ regarding cv-qualified function types.

4 There  is a (partial) ordering on cv-qualifiers, so that a type can be
  said to be more cv-qualified than another.  Table 1  shows  the  rela­
  tions that constitute this ordering.

                 Table 1--relations on const and volatile

                               +----------+
                  no cv-qualifier   <     const
                 no cv-qualifier   <     volatile
              no cv-qualifier  |<     const volatile
                  const     <  |  const volatile
                  volatile  <  |  const volatile
                               +----------+

5 In  this  document,  the  notation cv (or cv1, cv2, etc.), used in the
  description of types, represents an arbitrary  set  of  cv-qualifiers,
  i.e., one of {const}, {volatile}, {const, volatile}, or the empty set.
  _________________________
  12) The same representation and alignment requirements  are  meant  to
  imply interchangeability as arguments to functions, return values from
  functions, and members of unions.

  Cv-qualifiers applied to an array type attach to the  underlying  ele­
  ment type, so the notation "cv T," where T is an array type, refers to
  an array whose elements are so-qualified.  Such  array  types  can  be
  said  to  be more (or less) cv-qualified than other types based on the
  cv-qualification of the underlying element types.

  3.9.4  Type names                                    [basic.type.name]

1 [Note: Fundamental and compound types can be given names by the  type­
  def mechanism (_dcl.typedef_), and families of types and functions can
  be specified and named by the template mechanism (_temp_).  ]

  3.10  Lvalues and rvalues                                 [basic.lval]

1 Every expression is either an lvalue or an rvalue.

2 An lvalue refers to an object or function.  Some rvalue  expressions--
  those of class or cv-qualified class type--also refer to objects.13)

3 [Note: some  builtin  operators  and  function  calls  yield  lvalues.
  [Example:  if E is an expression of pointer type, then *E is an lvalue
  expression referring to the object or function to which E points.   As
  another example, the function
          int& f();
  yields an lvalue, so the call f() is an lvalue expression.  ] ]

4 [Note:  some  builtin  operators  expect  lvalue  operands.  [Example:
  builtin assignment operators all expect their left hand operands to be
  lvalues.   ]  Other  builtin  operators yield rvalues, and some expect
  them.  [Example: the unary and binary + operators expect rvalue  argu­
  ments  and  yield  rvalue  results.   ] The discussion of each builtin
  operator in clause _expr_ indicates whether it expects lvalue operands
  and whether it yields an lvalue.  ]

5 Constructor invocations and calls to functions that do not return ref­
  erences are always rvalues.  User defined operators are functions, and
  whether  such operators expect or yield lvalues is determined by their
  type.

6 Whenever an lvalue appears  in  a  context  where  an  lvalue  is  not
  expected,  the  lvalue  is  converted  to  an rvalue; see _conv.lval_,
  _conv.array_, and _conv.func_.

7 The discussion of reference initialization in  _dcl.init.ref_  and  of
  temporaries in _class.temporary_ indicates the behavior of lvalues and
  rvalues in other significant contexts.

  _________________________
  13)  Expressions  such as invocations of constructors and of functions
  that return a class type do in some sense refer to an object, and  the
  implementation can invoke a member function upon such objects, but the
  expressions are not lvalues.

8 Class rvalues can have cv-qualified types;  non-class  rvalues  always
  have  cv-unqualified types.  Rvalues always have complete types or the
  void type; lvalues may have incomplete types.

9 An lvalue for an object is necessary in order  to  modify  the  object
  except  that  an  rvalue  of class type can also be used to modify its
  referent under certain circumstances.   [Example:  a  member  function
  called for an object (_class.mfct_) can modify the object.  ]

10Functions cannot be modified, but pointers to functions can be modifi­
  able.

11A pointer to an incomplete type can be modifiable.  At some  point  in
  the  program  when  this pointer type is complete, the object at which
  the pointer points can also be modified.

12Array objects cannot be modified, but their elements  can  be  modifi­
  able.

13The  referent  of  a  const-qualified expression shall not be modified
  (through that expression), except that if it is of class type and  has
  a mutable component, that component can be modified (_dcl.type.cv_).

14If  an expression can be used to modify its object, it is called modi­
  fiable.  A program that attempts to modify an object through a nonmod­
  ifiable lvalue or rvalue expression is ill-formed.