______________________________________________________________________

  8   Declarators                                   [dcl.decl]

  ______________________________________________________________________

1 A declarator declares a single object, function,  or  type,  within  a
  declaration.  The init-declarator-list appearing in a declaration is a
  comma-separated sequence of declarators, each of  which  can  have  an
  initializer.
          init-declarator-list:
                  init-declarator
                  init-declarator-list , init-declarator
          init-declarator:
                  declarator initializeropt

2 The  two  components  of  a  declaration  are  the  specifiers  (decl-
  specifier-seq; _dcl.spec_) and the declarators (init-declarator-list).
  The  specifiers indicate the fundamental type, storage class, or other
  properties of the objects and functions being declared.  The  declara­
  tors specify the names of these objects and functions and (optionally)
  modify the type with operators such as * (pointer to) and () (function
  returning).   Initial  values  can  also be specified in a declarator;
  initializers are discussed in _dcl.init_ and _class.init_.

3 Each init-declarator in a declaration is analyzed separately as if  it
  was in a declaration by itself.1)

4 Declarators have the syntax
          declarator:
                  direct-declarator
                  ptr-operator declarator
  _________________________
  1) A declaration with several declarators is usually equivalent to the
  corresponding sequence of declarations each with a single  declarator.
  That is
          T  D1, D2, ... Dn;
  is usually equvalent to
          T  D1; T D2; ... T Dn;
  where T is a decl-specifier-seq and each Di is a init-declarator.  The
  exception occurs when one declarator  modifies  the  name  environment
  used by a following declarator, as in
          struct S { ... };
          S   S, T;  // declare two instances of struct S
  which is not equivalent to
          struct S { ... };
          S   S;
          S   T;   // error

          direct-declarator:
                  declarator-id
                  direct-declarator ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
                  direct-declarator [ constant-expressionopt ]
                  ( declarator )
          ptr-operator:
                  * cv-qualifier-seqopt
                  &
                  ::opt nested-name-specifier * cv-qualifier-seqopt
          cv-qualifier-seq:
                  cv-qualifier cv-qualifier-seqopt
          cv-qualifier:
                  const
                  volatile
          declarator-id:
                  id-expression
                  nested-name-specifieropt type-name
  A class-name has special meaning in a declaration of the class of that
  name and when qualified by that name using the scope resolution opera­
  tor :: (_expr.prim_, _class.ctor_, _class.dtor_).

  8.1  Type names                                             [dcl.name]

1 To  specify  type conversions explicitly, and as an argument of sizeof
  or new, the name of a type shall be specified.  This can be done  with
  a type-id, which is syntactically a declaration for an object or func­
  tion of that type that omits the name of the object or function.
          type-id:
                  type-specifier-seq abstract-declaratoropt
          type-specifier-seq:
                  type-specifier type-specifier-seqopt
          abstract-declarator:
                  ptr-operator abstract-declaratoropt
                  direct-abstract-declarator
          direct-abstract-declarator:
                  direct-abstract-declaratoropt ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
                  direct-abstract-declaratoropt [ constant-expressionopt ]
                  ( abstract-declarator )
  It is possible to identify uniquely  the  location  in  the  abstract-
  declarator  where the identifier would appear if the construction were
  a declarator in a declaration.  The named type is then the same as the
  type of the hypothetical identifier.  For example,
          int                 // int i
          int *               // int *pi
          int *[3]            // int *p[3]
          int (*)[3]          // int (*p3i)[3]
          int *()             // int *f()
          int (*)(double)     // int (*pf)(double)
  name  respectively  the  types integer, pointer to integer, array of 3
  pointers to integers, pointer to array of 3 integers, function  having
  no  parameters  and returning pointer to integer, and pointer to func­
  tion of double returning an integer.

2 A type can also be named  (often  more  easily)  by  using  a  typedef
  (_dcl.typedef_).

3 Note  that  an  exception-specification  does  not affect the function
  type, so its appearance in  an  abstract-declarator  will  have  empty
  semantics.

  8.2  Ambiguity resolution                              [dcl.ambig.res]

1 The  ambiguity  arising  from  the similarity between a function-style
  cast and a declaration mentioned in _stmt.ambig_ can also occur in the
  context  of  a  declaration.  In that context, it surfaces as a choice
  between a function declaration with a  redundant  set  of  parentheses
  around  a  parameter  name  and an object declaration with a function-
  style cast as the initializer.  Just as for statements, the resolution
  is  to  consider  any construct that could possibly be a declaration a
  declaration.  A declaration can be explicitly disambiguated by a  non­
  function-style cast or a = to indicate initialization.  For example,
          struct S {
              S(int);
          };
          void foo(double a)
          {
              S x(int(a));        // function declaration
              S y((int)a);        // object declaration
              S z = int(a);       // object declaration
          }

2 The  ambiguity  arising  from  the similarity between a function-style
  cast and a type-id can occur in many different contexts.  The  ambigu­
  ity  surfaces as a choice between a function-style cast expression and
  a declaration of a type.  The resolution is that  any  construct  that
  could  possibly be a type-id in its syntactic context shall be consid­
  ered a type-id.

3 For example,
          #include <stddef.h>
          char *p;
          void *operator new(size_t, int);
          void foo(int x)  {
                  new (int(*p)) int;      // new-placement expression
                  new (int(*[x]));        // new type-id
          }

4 For example,
          template <class T>
          struct S {
          T *p;
          };
          S<int()> x;             // type-id
          S<int(1)> y;            // expression (ill-formed)

5 For example,

          void foo()
          {
                  sizeof(int(1)); // expression
                  sizeof(int());  // type-id (ill-formed)
          }

6 For example,
          void foo()
          {
                  (int(1));       // expression
                  (int())1;       // type-id (ill-formed)
          }

  8.3  Meaning of declarators                              [dcl.meaning]

1 A list of declarators appears  after  an  optional  (_dcl.dcl_)  decl-
  specifier-seq  (_dcl.spec_).   Each  declarator  contains  exactly one
  declarator-id; it names the identifier that is declared.   A  declara­
  tor-id  shall  be a simple identifier, except for the following cases:
  the declaration of some special functions (_class.conv_, _class.dtor_,
  _over.oper_),  the definition of a member function (_class.mfct_), the
  definition of a static data member (_class.static_),  the  declaration
  of   a   friend   function   that   is   a  member  of  another  class
  (_class.friend_).  An auto, static, extern, register, friend,  inline,
  virtual,  or  typedef specifier applies directly to each declarator-id
  in a init-declarator-list; the type specified for  each  declarator-id
  depends on both the decl-specifier-seq and its declarator.

2 Thus, a declaration of a particular identifier has the form
          T D
  where  T is a decl-specifier-seq and D is a declarator.  The following
  subsections give an inductive procedure for determining the type spec­
  ified for the contained declarator-id by such a declaration.

3 First,  the decl-specifier-seq determines a type.  For example, in the
  declaration
          int unsigned i;
  the type specifiers  int  unsigned  determine  the  type  unsigned int
  (_dcl.type.simple_).  Or in general, in the declaration
          T D
  the decl-specifier-seq T determines the type T.

4 In  a  declaration  T D where D is an unadorned identifier the type of
  this identifier is T.

5 In a declaration T D where D has the form
          ( D1 )
  the type of the contained declarator-id is the same  as  that  of  the
  contained declarator-id in the declaration
          T D1
  Parentheses  do  not alter the type of the embedded declarator-id, but
  they can alter the binding of complex declarators.

  8.3.1  Pointers                                              [dcl.ptr]

1 In a declaration T D where D has the form
          * cv-qualifier-seqopt D1
  and the type of the identifier  in  the  declaration  T  D1  is  type-
  modifier  T, then the type of the identifier of D is type-modifier cv-
  qualifier-seq pointer to T.  The cv-qualifiers apply  to  the  pointer
  and not to the object pointed to.

2 For example, the declarations
          const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
          int i, *p, *const cp = &i;
  declare  ci,  a constant integer; pc, a pointer to a constant integer;
  cpc, a constant pointer to a constant integer, ppc,  a  pointer  to  a
  pointer to a constant integer; i, an integer; p, a pointer to integer;
  and cp, a constant pointer to integer.  The value of ci, cpc,  and  cp
  cannot  be  changed  after  initialization.   The  value  of pc can be
  changed, and so can the object pointed to by cp.  Examples of  correct
  operations are
          i = ci;
          *cp = ci;
          pc++;
          pc = cpc;
          pc = p;
          ppc = &pc;
  Examples of ill-formed operations are
          ci = 1;      // error
          ci++;        // error
          *pc = 2;     // error
          cp = &ci;    // error
          cpc++;       // error
          p = pc;      // error
          ppc = &p;    // error
  Each  is  unacceptable  because it would either change the value of an
  object declared const or allow it to be changed through an unqualified
  pointer later, for example:
          *ppc = &ci;  // okay, but would make p point to ci ...
                       // ... because of previous error
          *p = 5;      // clobber ci

3 volatile specifiers are handled similarly.

4 See also _expr.ass_ and _dcl.init_.

5 There can be no pointers to references (_dcl.ref_) or pointers to bit-
  fields (_class.bit_).

  8.3.2  References                                            [dcl.ref]

1 In a declaration T D where D has the form
          & D1
  and the type of the identifier  in  the  declaration  T  D1  is  type-
  modifier T, then the type of the identifier of D is type-modifier ref­
  erence to T.  At all times during the determination of a  type,  types

  of the form cv-qualified reference to T is adjusted to be reference to
  T.  For example, in
          typedef int& A;
          const A aref = 3;
  the type of aref is reference to int, not const reference to  int.   A
  declarator that specifies the type reference to cv void is ill-formed.

2 For example,
          void f(double& a) { a += 3.14; }
          // ...
              double d = 0;
              f(d);
  declares a to be a reference parameter of f so the call f(d) will  add
  3.14 to d.
          int v[20];
          // ...
          int& g(int i) { return v[i]; }
          // ...
          g(3) = 7;
  declares  the  function  g()  to  return  a reference to an integer so
  g(3)=7 will assign 7 to the fourth element of the array v.
          struct link {
              link* next;
          };

          link* first;
          void h(link*& p)  // `p' is a reference to pointer
          {
              p->next = first;
              first = p;
              p = 0;
          }
          void k()
          {
                  link* q = new link;
                  h(q);
          }
  declares p to be a reference to a pointer to link so h(q) will leave q
  with the value zero.  See also _dcl.init.ref_.

3 A reference may or may not require storage (_basic.stc_).

4 There  can be no references to references, no references to bit-fields
  (_class.bit_), no arrays of references, and no pointers to references.
  The   declaration   of   a  reference  shall  contain  an  initializer
  (_dcl.init.ref_) except when  the  declaration  contains  an  explicit
  extern specifier (_dcl.stc_), is a class member (_class.mem_) declara­
  tion within a class declaration, or is the declaration of an parameter
  or  a  return type (_dcl.fct_); see _basic.def_.  A reference shall be
  initialized to refer to a valid object or  function.   In  particular,
  null references are prohibited; no diagnostic is required.

  8.3.3  Pointers to members                                  [dcl.mptr]

1 In a declaration T D where D has the form
          ::opt nested-name-specifier :: * cv-qualifier-seqopt D1
  and the nested-name-specifier names a class, and the type of the iden­
  tifier in the declaration T D1 is type-modifier T, then  the  type  of
  the  identifier of D is type-modifier cv-qualifier-seq pointer to mem­
  ber of class nested-name-specifier of type T.

2 For example,
          class X {
          public:
              void f(int);
              int a;
          };
          class Y;

          int X::* pmi = &X::a;
          void (X::* pmf)(int) = &X::f;
          double X::* pmd;
          char Y::* pmc;
  declares pmi, pmf, pmd and pmc to be a pointer to a  member  of  X  of
  type int, a pointer to a member of X of type void(int), a pointer to a
  member of X of type double and a pointer to a member of Y of type char
  respectively.  The declaration of pmd is well-formed even though X has
  no members of type double.  Similarly, the declaration of pmc is well-
  formed  even  though Y is an incomplete type.  pmi and pmf can be used
  like this:
          X obj;
          //...
          obj.*pmi = 7;   // assign 7 to an integer
                          // member of obj
          (obj.*pmf)(7);  // call a function member of obj
                          // with the argument 7

3 Note that a pointer to member cannot point to a  static  member  of  a
  class  (_class.static_),  a  member  with  reference type, or cv void.
  There are no references to members.   See  also  _expr.mptr.oper_  and
  _expr.unary_.

  8.3.4  Arrays                                              [dcl.array]

1 In a declaration T D where D has the form
          D1 [constant-expressionopt]
  and  the  type  of  the  identifier  in  the declaration T D1 is type-
  modifier T, then the type of the identifier of D is an array type.   T
  shall  not  be  a  reference  type, an incomplete type, or an abstract
  class type.  If the constant-expression (_expr.const_) is present, its
  value  shall  be greater than zero.  The constant expression specifies
  the bound of (number of elements in) the array.  If the value  of  the
  constant  expression is N, the array has N elements numbered 0 to N-1,
  and the type of the identifier of D is type-modifier array of N T.  If
  the constant expression is omitted, the type of the identifier of D is

  type-modifier array of unknown bound of T, an incomplete object  type.
  The  type type-modifier array of N T is a different type from the type
  type-modifier array of unknown bound of T, see _basic.types_.  Any cv-
  qualifiers  that appear in type-modifier are applied to the type T and
  not to the array type, as in this example:
          typedef int A[5], AA[2][3];
          const A x;      // type is ``array of 5 const int''
          const AA y;     // type is ``array of 2 array of 3 const int''

2 An array can be  constructed  from  one  of  the  fundamental  types2)
  (except void), from a pointer, from a pointer to member, from a class,
  or from another array.

3 When several array of specifications are adjacent, a  multidimensional
  array  is created; the constant expressions that specify the bounds of
  the arrays can be omitted only for the first member of  the  sequence.
  This  elision  is  useful  for function parameters of array types, and
  when the array is external and the definition, which  allocates  stor­
  age,  is  given  elsewhere.  The first constant-expression can also be
  omitted  when  the  declarator   is   followed   by   an   initializer
  (_dcl.init_).  In this case the bound is calculated from the number of
  initial elements (say, N) supplied (_dcl.init.aggr_), and the type  of
  the identifier of D is array of N T.

4 The declaration
          float fa[17], *afp[17];
  declares  an  array of float numbers and an array of pointers to float
  numbers.  The declaration
          static int x3d[3][5][7];
  declares a static  three-dimensional  array  of  integers,  with  rank
  3×5×7.   In complete detail, x3d is an array of three items; each item
  is an array of five arrays; each of the latter arrays is an  array  of
  seven  integers.   Any  of  the  expressions  x3d,  x3d[i], x3d[i][j],
  x3d[i][j][k] can reasonably appear in an expression.

5 Conversions  affecting  lvalues  of  array  type  are   described   in
  _conv.array_.    Objects  of  array  types  cannot  be  modified,  see
  _basic.lval_.

6 Except where it has been declared for a class (_over.sub_),  the  sub­
  script operator [] is interpreted in such a way that E1[E2] is identi­
  cal to *((E1)+(E2)).  Because of the conversion rules that apply to +,
  if  E1  is an array and E2 an integer, then E1[E2] refers to the E2-th
  member of E1.  Therefore,  despite  its  asymmetric  appearance,  sub­
  scripting is a commutative operation.

7 A consistent rule is followed for multidimensional arrays.  If E is an
  n-dimensional array of rank i×j×...×k, then E appearing in an  expres­
  sion is converted to a pointer to an (n-1)-dimensional array with rank
  j×...×k.  If the * operator, either  explicitly  or  implicitly  as  a
  result  of subscripting, is applied to this pointer, the result is the
  _________________________
  2) The enumeration types are included in the fundamental types.

  pointed-to (n-1)-dimensional array, which itself is  immediately  con­
  verted into a pointer.

8 For example, consider
          int x[3][5];
  Here  x  is a 3×5 array of integers.  When x appears in an expression,
  it is converted to a pointer to (the  first  of  three)  five-membered
  arrays  of  integers.   In the expression x[i], which is equivalent to
  *(x+i), x is first converted to a pointer as described;  then  x+i  is
  converted to the type of x, which involves multiplying i by the length
  of the object  to  which  the  pointer  points,  namely  five  integer
  objects.   The  results  are added and indirection applied to yield an
  array (of five integers), which in turn is converted to a  pointer  to
  the  first  of  the  integers.  If there is another subscript the same
  argument applies again; this time the result is an integer.

9 It follows from all this that arrays in C++ are stored row-wise  (last
  subscript varies fastest) and that the first subscript in the declara­
  tion helps determine the amount of storage consumed by  an  array  but
  plays no other part in subscript calculations.

  8.3.5  Functions                                             [dcl.fct]

1 In a declaration T D where D has the form
          D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
  and the type of the contained declarator-id in the declaration T D1 is
  type-modifier T1, the type of the declarator-id in D is  type-modifier
  cv-qualifier-seqopt   function  with  parameters  of  type  parameter-
  declaration-clause and returning T1; a type of this form is a function
  type3).
          parameter-declaration-clause:
                  parameter-declaration-listopt ...opt
                  parameter-declaration-list , ...
          parameter-declaration-list:
                  parameter-declaration
                  parameter-declaration-list , parameter-declaration
          parameter-declaration:
                  decl-specifier-seq declarator
                  decl-specifier-seq declarator = assignment-expression
                  decl-specifier-seq abstract-declaratoropt
                  decl-specifier-seq abstract-declaratoropt = assignment-expression

2 The parameter-declaration-clause determines the arguments that can  be
  specified,  and their processing, when the function is called.  If the
  parameter-declaration-clause terminates with an ellipsis,  the  number
  of  arguments  is known only to be equal to or greater than the number
  of parameters specified; if it is empty, the function takes  no  argu­
  ments.  The parameter list (void) is equivalent to the empty parameter
  list.  Except for this special case, void shall  not  be  a  parameter
  type  (though  types  derived  from  void, such as void*, can).  Where
  _________________________
  3)  As indicated by the syntax, cv-qualifiers are a significant compo­
  nent in function return types.

  syntactically correct, , ...  is synonymous with  ....   The  standard
  header  <cstdarg>  contains a mechanism for accessing arguments passed
  using the ellipsis (see _expr.call_ and _lib.support.runtime_).

3 A single name can be used for several different functions in a  single
  scope;  this is function overloading (_over_).  All declarations for a
  function with a given parameter list shall agree exactly both  in  the
  type  of  the value returned and in the number and type of parameters;
  the presence or absence of the ellipsis  is  considered  part  of  the
  function  type.  The type of each parameter is determined from its own
  decl-specifier-seq and declarator.  After determining the type of each
  parameter, any parameter of type array of T or function returning T is
  adjusted to be pointer to  T  or  pointer  to  function  returning  T,
  respectively.   After  producing  the list of parameter types, several
  transformations take place upon the types.  Any cv-qualifier modifying
  a  parameter  type  is deleted; e.g., the type void(const int) becomes
  void(int).  Such cv-qualifiers  affect  only  the  definition  of  the
  parameter  within  the  body  of  the function.  If the storage-class-
  specifier  register  modifies  a  parameter  type,  the  specifier  is
  deleted;  e.g.,  register  char*  becomes  char*.  Such storage-class-
  qualifiers affect only the definition of the parameter within the body
  of the function.  The resulting list of transformed parameter types is
  the function's parameter type list.

  +-------                      BEGIN BOX 1                     -------+
  Issue: a definition for signature will be added as soon as the  seman­
  tics are made precise.
  +-------                       END BOX 1                      -------+

  The return type and the parameter type list, but not the default argu­
  ments (_dcl.fct.default_), are part of the function type.  If the type
  of a parameter includes a type of the form pointer to array of unknown
  bound of T or reference to array of unknown bound of T, the program is
  ill-formed.4)  A cv-qualifier-seq can only be part of a declaration or
  definition of a nonstatic member function, and of a pointer to a  mem­
  ber function; see _class.this_.  It is part of the function type.

4 Functions  cannot return arrays or functions, although they can return
  pointers and references to such things.  There are no arrays of  func­
  tions, although there can be arrays of pointers to functions.

5 Types shall not be defined in return or parameter types.

6 The  parameter-declaration-clause  is  used to check and convert argu­
  ments in calls and  to  check  pointer-to-function  and  reference-to-
  function assignments and initializations.

  _________________________
  4) This excludes parameters of type ptr-arr-seq T2 where T2 is pointer
  to array of unknown bound of T and where  ptr-arr-seq  means  any  se­
  quence  of  pointer to and array of modifiers.  This exclusion applies
  to the parameters of the function, and if a parameter is a pointer  to
  function then to its parameters also, etc.

7 An  identifier can optionally be provided as a parameter name; if pre­
  sent in a function declaration, it cannot be used since it goes out of
  scope  at  the end of the function declarator (_basic.scope_); if pre­
  sent in a function definition (_dcl.fct.def_), it  names  a  parameter
  (sometimes  called  formal  argument).  In particular, parameter names
  are also optional in function definitions and names used for a parame­
  ter  in  different  declarations and the definition of a function need
  not be the same.

8 The declaration
          int i,
              *pi,
              f(),
              *fpi(int),
              (*pif)(const char*, const char*);
              (*fpif(int))(int);
  declares an integer i, a pointer pi to an integer, a function f taking
  no  arguments and returning an integer, a function fpi taking an inte­
  ger argument and returning a pointer to an integer, a pointer pif to a
  function  which  takes two pointers to constant characters and returns
  an integer, a function fpif taking an integer argument and returning a
  pointer  to  a  function that takes an integer argument and returns an
  integer.  It is especially useful to compare fpi and pif.  The binding
  of *fpi(int) is *(fpi(int)), so the declaration suggests, and the same
  construction in an expression requires, the calling of a function fpi,
  and  then  using  indirection through the (pointer) result to yield an
  integer.  In the declarator  (*pif)(const  char*,  const  char*),  the
  extra parentheses are necessary to indicate that indirection through a
  pointer to a function yields a function, which is then called.

9 Typedefs are sometimes convenient when the return type of  a  function
  is  complex.   For  example,  the  function fpif above could have been
  declared
          typedef int  IFUNC(int);
          IFUNC*  fpif(int);

10The declaration
          fseek(FILE*, long, int);
  declares a function taking three arguments  of  the  specified  types.
  Since  no  return  value  type  is  specified  it  is  taken to be int
  (_dcl.type_).  The declaration
          printf(const char* ...);
  declares a function that can be called with varying numbers and  types
  of arguments.  For example,
          printf("hello world");
          printf("a=%d b=%d", a, b);
  It  shall  always  have  a  value, however, that can be converted to a
  const char* as its first argument.

  8.3.6  Default arguments                             [dcl.fct.default]

1 If an expression is specified in a parameter declaration this  expres­
  sion is used as a default argument.  Default arguments will be used in
  calls where trailing arguments are missing.

2 The declaration
          point(int = 3, int = 4);
  declares a function that can be called with zero, one,  or  two  argu­
  ments of type int.  It can be called in any of these ways:
          point(1,2);  point(1);  point();
  The  last  two  calls  are  equivalent  to  point(1,4) and point(3,4),
  respectively.

3 A default argument expression shall be specified only in  the  parame­
  ter-declaration-clause  of  a  function  declaration or in a template-
  parameter  (_temp.param_).   If  it  is  specified  in  a   parameter-
  declaration-clause,   it  shall  not  occur  within  a  declarator  or
  abstract-declarator of a parameter-declaration.5)

  +-------                      BEGIN BOX 2                     -------+
  This restriction, voted in at the Valley Forge meeting, is expected to
  be  reviewed at the Austin meeting.  Mike Miller has promised a paper.
  +-------                       END BOX 2                      -------+

4 Default arguments can be added in later declarations  of  a  function,
  but  only  in  the  same scope.  Declarations in different scopes have
  completely distinct sets of default arguments.  That is,  declarations
  in  inner scopes do not acquire default arguments from declarations in
  outer scopes, and vice versa.  In a given  function  declaration,  all
  parameters  subsequent  to  a  parameter with a default argument shall
  have default arguments supplied in this or previous  declarations.   A
  default  argument  shall  not be redefined by a later declaration (not
  even to the same value).  For example:

  _________________________
  5) This means that default arguments cannot appear,  for  example,  in
  declarations  of  pointers  to  functions, references to functions, or
  typedef declarations.

          void f(int, int);
          void f(int, int = 7);
          void h()
          {
              f(3);                       // ok, calls f(3, 7)
              void f(int = 1, int);       // error: does not use default
                                          // from surrounding scope
          }
          void m()
          {
              void f(int, int);           // has no defaults
              f(4);                       // error: wrong number of arguments
              void f(int, int = 5);       // ok
              f(4);                       // ok, calls f(4, 5);
              void f(int, int = 5);       // error: cannot redefine, even to
                                          // same value
          }
          void n()
          {
              f(6);                       // ok, calls f(6, 7)
          }
  Declarations of a given nonmember function  in  different  translation
  units  need not specify the same default arguments.  Declarations of a
  given member function in different translation units,  however,  shall
  specify  the  same  default arguments (the accumulated sets of default
  arguments at the end of the translation units shall be the same).

  +-------                      BEGIN BOX 3                     -------+
  This was decided on the basis of guesses regarding the One  Definition
  Rule and should be reviewed once that section is finished.
  +-------                       END BOX 3                      -------+

5 Default  argument expressions in non-member functions have their names
  bound and their types checked at the point  of  declaration,  and  are
  evaluated  at  each  point  of  call.   In  member functions, names in
  default argument expressions are bound at the end of the class  decla­
  ration,  like names in inline member function bodies (_class.inline_).
  In the following example, g will be called with the value f(1):
          int a = 1;
          int f(int);
          int g(int x = f(a)); // default argument: f(::a)

          void h() {
              a = 2;
              {
                  int a = 3;
                  g();        // g(f(::a))
              }
          }
  Local variables shall not be used  in  default  argument  expressions.
  For example,

          void f()
          {
              int i;
              extern void g(int x = i);   // error
              // ...
          }
  this  shall  not  be  used in a default argument of a member function.
  For example,
          class A {
              void f(A* p = this);        // error
          };

6 Note that default arguments are evaluated before entry into a function
  and  that the order of evaluation of function arguments is implementa­
  tion dependent.  Consequently, parameters of a function shall  not  be
  used  in default argument expressions, even if they are not evaluated.
  Parameters of a function declared before a default argument expression
  are in scope and can hide namespace and class member names.  For exam­
  ple,
          int a;
          int f(int a, int b = a);    // error: parameter `a'
                                      // used as default argument
          typedef int I;
          int g(float I, int b = I(2)); // error: `float' called
          int h(int a, int b = sizeof(a));  // error, parameter `a' used
                                            // in default argument

7 Similarly, a nonstatic member shall not be used in a default  argument
  expression,  even if it is not evaluated, unless it appears as the id-
  expression of a class  member  access  expression  (_expr.ref_).   For
  example, the declaration of X::mem1() in the following example is ill-
  formed because no object is supplied for  the  nonstatic  member  X::a
  used as an initializer.
          int b;
          class X {
              int a;
              mem1(int i = a); // error: nonstatic member `a'
                               // used as default argument
              mem2(int i = b); // ok;  use X::b
              static b;
          };
  The  declaration  of X::mem2() is meaningful, however, since no object
  is needed to access the static member  X::b.   Classes,  objects,  and
  members are described in _class_.

8 A default argument is not part of the type of a function.

          int f(int = 0);

          void h()
          {
              int j = f(1);
              int k = f();      // fine, means f(0)
          }

          int (*p1)(int) = &f;
          int (*p2)() = &f;     // error: type mismatch
  When  a declaration of a function is introduced by way of a using dec­
  laration (_namespace.udecl_), any default argument information associ­
  ated with the declaration is imported as well.

  +-------                      BEGIN BOX 4                     -------+
  Can  additional  default arguments be added to the function thereafter
  by way of redeclarations of the function?  Can the function  be  rede­
  clared  in  the namespace with added default arguments, and if so, are
  those added arguments visible to those who have imported the  function
  via using?
  +-------                       END BOX 4                      -------+

9 An overloaded operator (_over.oper_) shall not have default arguments.

10A virtual function call (_class.virtual_) uses the  default  arguments
  in  the  declaration  of the virtual function determined by the static
  type of the pointer or reference denoting the object.   An  overriding
  function  in  a  derived class does not acquire default arguments from
  the function it overrides.  For example,
          struct A {
              virtual void f(int a = 7);
          };
          struct B : public A {
              void f(int a);
          };
          void m()
          {
              B* pb = new B;
              A* pa = pb;
              pa->f();          // ok, calls pa->A::f(7)
              pb->f();          // error: wrong number of arguments for B::f()
          }

  8.4  Function definitions                                [dcl.fct.def]

1 Function definitions have the form
          function-definition:
                  decl-specifier-seqopt declarator ctor-initializeropt function-body

          function-body:
                  compound-statement
  The declarator in a function-definition shall have the form

          D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
  as described in _dcl.fct_.  A function can be defined only  in  names­
  pace or class scope.

2 The  parameters  are  in the scope of the outermost block of the func­
  tion-body.

3 A simple example of a complete function definition is
          int max(int a, int b, int c)
          {
              int m = (a > b) ? a : b;
              return (m > c) ? m : c;
          }
  Here int is the decl-specifier-seq; max(int a, int b, int  c)  is  the
  declarator; { /* ... */ } is the function-body.

4 A ctor-initializer is used only in a constructor; see _class.ctor_ and
  _class.init_.

5 A cv-qualifier-seq can be part of a non-static member function  decla­
  ration,  non-static  member  function definition, or pointer to member
  function only; see _class.this_.  It is part of the function type.

6 Note that unused parameters need not be named.  For example,
          void print(int a, int)
          {
              printf("a = %d\n",a);
          }

  8.5  Initializers                                           [dcl.init]

1 A declarator can specify an initial value  for  the  identifier  being
  declared.  The identifier designates an object or reference being ini­
  tialized.  The process of initialization described in the remainder of
  this  subclause (_dcl.init_) applies also to initializations specified
  by other syntactic contexts, such as the  initialization  of  function
  parameters  with argument expressions (_expr.call_) or the initializa­
  tion of return values (_stmt.return_).
          initializer:
                  = initializer-clause
                  ( expression-list )
          initializer-clause:
                  assignment-expression
                  { initializer-list ,opt }
                  { }
          initializer-list:
                  initializer-clause
                  initializer-list , initializer-clause

2 Automatic, register, static, and external variables of namespace scope
  can  be  initialized  by arbitrary expressions involving constants and
  previously declared variables and functions.

          int f(int);
          int a = 2;
          int b = f(a);
          int c(b);

3 Default   argument    expressions    are    more    restricted;    see
  _dcl.fct.default_.

4 The  order  of  initialization  of  static  objects  is  described  in
  _basic.start_ and _stmt.dcl_.

5 Variables with static storage duration (_basic.stc_) that are not ini­
  tialized and do not have a user-declared constructor are guaranteed to
  start off as zero converted to the appropriate type.  If the object is
  a  class  or struct, its nonstatic data members start off as zero con­
  verted to the appropriate type.  If the object is a union,  its  first
  nonstatic  data member starts off as zero converted to the appropriate
  type.  The initial values of automatic and register variables that are
  not initialized are indeterminate.

6 An  initializer  for  a  static member is in the scope of the member's
  class.  For example,
          int a;

          struct X {
              static int a;
              static int b;
          };

          int X::a = 1;
          int X::b = a;   // X::b = X::a

7 The form of initialization  (using  parentheses  or  =)  is  generally
  insignificant, but does matter when the entity being initialized has a
  class type; see below.  A parenthesized initializer can be a  list  of
  expressions only when the entity being initialized has a class type.

8 Note that since () is not an initializer,
          X a();
  is not the declaration of an object of class X, but the declaration of
  a function taking no argument and returning an X.

9 The initialization that occurs in argument passing and function return
  is equivalent to the form
          T x = a;
  The  initialization  that  occurs  in  new  expressions  (_expr.new_),
  static_cast expressions (_expr.static.cast_), functional notation type
  conversions  (_expr.type.conv_),  and  base  and  member  initializers
  (_class.base.init_) is equivalent to the form
          T x(a);

10The semantics of initializers are as follows.  The destination type is
  the  type  of the object or reference being initialized and the source
  type is the type of the initializer expression.  The  source  type  is

  not  defined  when  the  initializer is brace-enclosed or when it is a
  parenthesized list of expressions.

  --If the destination type is a reference type, see _dcl.init.ref_.

  --If the destination type is an array of characters  or  an  array  of
    wchar_t,   and   the   initializer   is   a   string   literal,  see
    _dcl.init.string_.

  --Otherwise, if the destination type is an array, see _dcl.init.aggr_.

  --If the destination type is a (possibly cv-qualified) class type that
    is an aggregate (_dcl.init.aggr_), and the initializer is  a  brace-
    enclosed list, see _dcl.init.aggr_.

  --Otherwise,  if  the  destination  type  is a (possibly cv-qualified)
    class type and the initializer has the parenthesized form, construc­
    tors  are  considered.   The  applicable constructors are enumerated
    (_over.match.ctor_), and the best one  is  chosen  through  overload
    resolution (_over.match_).  The constructor so selected is called to
    initialize the object, with the  initializer  expression(s)  as  its
    argument(s).   If no constructor applies, or the overload resolution
    is ambiguous, the initialization is ill-formed.

  --Otherwise, if the destination type or the source type is a (possibly
    cv-qualified)  class  type, user-defined conversions are considered.
    The   applicable    user-defined    conversions    are    enumerated
    (_over.match.user_),  and  the  best  one is chosen through overload
    resolution (_over.match_).  The user-defined conversion so  selected
    is  called  to  copy  or convert the initializer expression into the
    object being initialized.  If the conversion cannot be  done  or  is
    ambiguous, the initialization is ill-formed.

  --Otherwise,  the initial value of the object being initialized is the
    (possibly converted) value of the initializer expression.   Standard
    conversions  (clause  _conv_) will be used, if necessary, to convert
    the initializer expression to the unqualified version of the  desti­
    nation  type;  no  user-defined  conversions are considered.  If the
    conversion cannot be done, the initialization is  ill-formed.   Note
    that  an  expression  of type cv1 T can initialize an object of type
    cv2 T independently of the cv-qualifiers cv1 and cv2.  For example,
              int a;
              const int b = a;
              int c = b;

  8.5.1  Aggregates                                      [dcl.init.aggr]

1 An aggregate is an array or an object of a  class  (_class_)  with  no
  user-declared  constructors  (_class.ctor_),  no  private or protected
  members (_class.access_), no base classes  (_class.derived_),  and  no
  virtual functions (_class.virtual_).  When an aggregate is initialized
  the initializer can be an initializer-clause consisting  of  a  brace-
  enclosed,  comma-separated list of initializers for the members of the
  aggregate, written in increasing subscript or member  order.   If  the

  aggregate contains subaggregates, this rule applies recursively to the
  members of the subaggregate.  If there are fewer initializers  in  the
  list  than  there  are members of the aggregate, then the aggregate is
  padded with zeros of the appropriate types.6)

2 For example,
          struct S { int a; char* b; int c; };
          S ss = { 1, "asdf" };
  initializes ss.a with 1, ss.b with "asdf", and ss.c with zero.

3 An  aggregate  that  is  a class can also be initialized with a single
  non-brace-enclosed expression, as described in _dcl.init_.

4 Braces can be elided as follows.   If  the  initializer-clause  begins
  with  a  left  brace, then the succeeding comma-separated list of ini­
  tializers initializes the members of the aggregate;  it  is  erroneous
  for there to be more initializers than members.  If, however, the ini­
  tializer-clause or a subaggregate does not begin with  a  left  brace,
  then  only  enough elements from the list are taken to account for the
  members of the aggregate; any remaining elements are left to  initial­
  ize the next member of the aggregate of which the current aggregate is
  a part.

5 For example,
          int x[] = { 1, 3, 5 };
  declares and initializes x as a one-dimensional array that  has  three
  members, since no size was specified and there are three initializers.
          float y[4][3] = {
              { 1, 3, 5 },
              { 2, 4, 6 },
              { 3, 5, 7 },
          };
  is a completely-bracketed initialization: 1, 3, and 5  initialize  the
  first  row  of  the  array y[0], namely y[0][0], y[0][1], and y[0][2].
  Likewise the next two lines initialize y[1] and y[2].  The initializer
  ends  early  and  therefore y[3] is initialized with zeros.  Precisely
  the same effect could have been achieved by
          float y[4][3] = {
              1, 3, 5, 2, 4, 6, 3, 5, 7
          };
  The last (rightmost) index varies fastest (_dcl.array_).

6 The initializer for y begins with a left brace, but the one  for  y[0]
  does  not,  therefore three elements from the list are used.  Likewise
  the next three are taken successively for y[1] and y[2].  Also,
          float y[4][3] = {
              { 1 }, { 2 }, { 3 }, { 4 }
          };
  initializes the first column  of  y  (regarded  as  a  two-dimensional
  array) and leaves the rest zero.
  _________________________
  6) The syntax provides for empty initializer clauses, but  nonetheless
  C++ does not have zero length arrays.

7 Initialization  of  arrays of objects of a class with non-trivial con­
  structors (_class.ctor_) is described in _class.expl.init_.

8 The initializer for a  union  with  no  user-declared  constructor  is
  either  a single expression of the same type, or a brace-enclosed ini­
  tializer for the first member of the union.  For example,
          union u { int a; char* b; };

          u a = { 1 };
          u b = a;
          u c = 1;              // error
          u d = { 0, "asdf" };  // error
          u e = { "asdf" };     // error

9 There shall not be more initializers than there are  members  or  ele­
  ments to initialize.  For example,
          char cv[4] = { 'a', 's', 'd', 'f', 0 };  // error
  is ill-formed.

  8.5.2  Character arrays                              [dcl.init.string]

1 A char array (whether plain char, signed, or unsigned) can be initial­
  ized by a string; a wchar_t  array  can  be  initialized  by  a  wide-
  character  string;  successive characters of the string initialize the
  members of the array.  For example,
          char msg[] = "Syntax error on line %s\n";
  shows a character array whose members are initialized with  a  string.
  Note  that  because  '\n' is a single character and because a trailing
  '\0' is appended, sizeof(msg) is 25.

2 There shall not be more initializers than there  are  array  elements.
  For example,
          char cv[4] = "asdf";  // error
  is ill-formed since there is no space for the implied trailing '\0'.

  8.5.3  References                                       [dcl.init.ref]

1 A  variable  declared  to  be  a  T&,  that  is  reference  to  type T
  (_dcl.ref_), shall be initialized by an object, or function, of type T
  or by an object that can be converted into a T.  For example,

          int g(int);
          void f()
          {
              int i;
              int& r = i;  // `r' refers to `i'
              r = 1;       // the value of `i' becomes 1
              int* p = &r; // `p' points to `i'
              int& rr = r; // `rr' refers to what `r' refers to,
                           // that is, to `i'
              int (&rg)(int) = g; // `rg' refers to the function `g'
              rg(i);              // calls function `g'
              int a[3];
              int (&ra)[3] = a;   // `ra' refers to the array `a'
              ra[1] = i;          // modifies `a[1]'
          }

2 A  reference  cannot  be changed to refer to another object after ini­
  tialization.  Note that initialization of a reference is treated  very
  differently from assignment to it.  Argument passing (_expr.call_) and
  function value return (_stmt.return_) are initializations.

3 The initializer can be omitted for a reference  only  in  a  parameter
  declaration (_dcl.fct_), in the declaration of a function return type,
  in the declaration of a class  member  within  its  class  declaration
  (_class.mem_), and where the extern specifier is explicitly used.  For
  example,
          int& r1;         // error: initializer missing
          extern int& r2;  // ok

4 Given types cv1 T1 and cv2 T2, cv1 T1 is reference-related  to  cv2 T2
  if  T1 is the same type as T2, or T1 is a base class of T2.  cv1 T1 is
  reference-compatible with cv2 T2 if T1 is reference-related to T2  and
  cv1 is the same cv-qualification as, or greater cv-qualification than,
  cv2.  For purposes of overload resolution,  cases  for  which  cv1  is
  greater   cv-qualification  than  cv2  are  identified  as  reference-
  compatible with added qualification  (see  _over.ics.rank_).   In  all
  cases where the reference-related or reference-compatible relationship
  of two types is used to establish the validity of a reference binding,
  and T1 is a base class of T2, a program that necessitates such a bind­
  ing is ill-formed if T1 is an inaccessible (_class.access_) or ambigu­
  ous (_class.member.lookup_) base class of T2.

5 A  reference  to  type  cv1 T1 is initialized by an expression of type
  cv2 T2 as follows:

  --If the initializer expression is an lvalue (but not an lvalue for  a
    bit-field), and

6
    --cv1 T1 is reference-compatible with cv2 T2, or

    --the  initializer  expression  can  be  implicitly  converted to an
      lvalue of type cv3 T1, where cv3 is the same cv-qualification  as,
      or lesser cv-qualification than, cv1, 7) then
  _________________________
  7)  This requires a conversion function (_class.conv.fct_) returning a

7   the reference  is  bound  directly  to  the  initializer  expression
    lvalue.   Note that the usual lvalue-to-rvalue (_conv.lval_), array-
    to-pointer  (_conv.array_),  and  function-to-pointer  (_conv.func_)
    standard  conversions  are not needed, and therefore are suppressed,
    when such direct bindings to lvalues are done.
              double d = 2.0;
              double& rd = d;         // rd refers to `d'
              const double& rcd = d;  // rcd refers to `d'

              struct A { };
              struct B : public A { } b;
              A& ra = b;              // ra refers to A sub-object in `b'
              const A& rca = b;       // rca refers to A sub-object in `b'

8
  --Otherwise, the reference shall  be  to  a  non-volatile  const  type
    (i.e., cv1 shall be const).
              double& rd2 = 2.0;      // error: not an lvalue and reference
                                      //   not const
              int  i = 2;
              double& rd3 = i;        // error: type mismatch and reference
                                      //   not const

    --If  the initializer expression is an rvalue, with T2 a class type,
      and cv1 T1 is reference-compatible with cv2 T2, the  reference  is
      bound  in one of the following ways (the choice is implementation-
      defined):

      --The reference is bound directly to the object represented by the
        rvalue (see _basic.lval_) or to a sub-object within that object.

      --A temporary of type cv1 T2 [sic] is created,  and  a  copy  con­
        structor  is  called  to  copy the entire rvalue object into the
        temporary.  The reference is bound to the temporary or to a sub-
        object within the temporary.  8)

9     The appropriate copy constructor must be callable whether  or  not
      the copy is actually done.
                  struct A { };
                  struct B : public A { } b;
                  extern B f();
                  const A& rca = f();     // Either bound directly or
                                          //   the entire B object is copied and
                                          //   the reference is bound to the
                                          //   A sub-object of the copy

  _________________________
  reference type, and therefore applies only when T2 is a class type.
  8) Clearly, if the reference initialization being processed is one for
  the first argument of a copy constructor call, an implementation  must
  eventually choose the direct-binding alternative to avoid infinite re­
  cursion.

10
    --Otherwise,  a  temporary of type cv1 T1 is created and initialized
      from the  initializer  expression  using  the  rules  for  a  non-
      reference  initialization  (_dcl.init_).   The  reference  is then
      bound to the temporary.  If T1 is  reference-related  to  T2,  cv1
      must  be the same cv-qualification as, or greater cv-qualification
      than, cv2; otherwise, the program is ill-formed.
                  const double& rcd2 = 2; // rcd2 refers to temporary
                                          // with value `2.0'
                  const volatile int cvi = 1;
                  const int& r = cvi;     // error: type qualifiers dropped

11  _class.temporary_ describes the lifetime  of  temporaries  bound  to
    references.