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
                  init-declarator-list , 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
                  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 ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
                  direct-declarator [ constant-expressionopt ]
                  ( declarator )
                  * cv-qualifier-seqopt
                  ::opt nested-name-specifier * cv-qualifier-seqopt
                  cv-qualifier cv-qualifier-seqopt
                  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,
  new, or typeid, 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 function of that type that omits the name of the  object  or
                  type-specifier-seq abstract-declaratoropt
                  type-specifier type-specifier-seqopt
                  ptr-operator abstract-declaratoropt
                  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.  [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 function of double returning an integer." ]

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

  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.  [Example:
          struct S {
          void foo(double a)
              S x(int(a));        // function declaration
              S x(int());         // function declaration
              S y((int)a);        // object declaration
              S z = int(a);       // object declaration
   --end example]

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 [Example:
          #include <cstddef>
          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 another example,
          template <class T>
          struct S {
          T *p;
          S<int()> x;             // type-id
          S<int(1)> y;            // expression (ill-formed)

5 For another example,

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

6 For another example,
          void foo()
                  (int(1));       // expression
                  (int())1;       // type-id (ill-formed)
   --end example]

  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.  In a declaration
          T D
  the decl-specifier-seq T determines the type T." [Example: in the dec­
          int unsigned i;
  the  type  specifiers  int  unsigned  determine the type unsigned int"
  (_dcl.type.simple_).  ]

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 "derived-
  declarator-type-list T," then the type  of  the  identifier  of  D  is
  "derived-declarator-type-list  cv-qualifier-seq pointer to T." The cv-
  qualifiers apply to the pointer and not to the object pointed to.

2 [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 some
  correct operations are
          i = ci;
          *cp = ci;
          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 a cv-
  unqualified pointer later, for example:
          *ppc = &ci;  // okay, but would make p point to ci ...
                       // ... because of previous error
          *p = 5;      // clobber ci
   --end example]

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 "derived-
  declarator-type-list T," then the type  of  the  identifier  of  D  is

  "derived-declarator-type-list reference to T." At all times during the
  determination of a type, any type of the form "cv-qualifier-seq refer­
  ence to T" is adjusted to be "reference to T".  [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-

2 [Example:
          void f(double& a) { a += 3.14; }
          // ...
              double d = 0;
  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.  For
  another example,
          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;
  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 It  is  unspecified  whether  or  not  a  reference  requires  storage

4 There shall be no references to  references,  no  references  to  bit-
  fields (_class.bit_), no arrays of references, and no pointers to ref­
  erences.  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 a 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 "derived-declarator-type-list T,"
  then the type of the identifier of D is  "derived-declarator-type-list
  cv-qualifier-seq  pointer  to member of class nested-name-specifier of
  type T."

2 [Example:
          class X {
              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
   --end example]

3 A pointer to member shall not point to a  static  member  of  a  class
  (_class.static_),  a  member with reference type, or "cv void." [Note:
  There  is  no   "reference-to-member"   type   in   C++.    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 "derived-
  declarator-type-list T," then the type of the identifier of  D  is  an
  array  type.   T  shall not be a reference type, an incomplete type, a
  function 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
  "derived-declarator-type-list  array  of N T." If the constant expres­
  sion is omitted,  the  type  of  the  identifier  of  D  is  "derived-
  declarator-type-list  array  of  unknown  bound  of  T," an incomplete
  object type.  The type "derived-declarator-type-list array of N T"  is
  a  different type from the type "derived-declarator-type-list array of
  unknown bound of T," see  _basic.types_.   At  all  times  during  the
  determination  of a type, any type of the form "cv-qualifier-seq array
  of N T" is adjusted to "array of N cv-qualifier-seq T"  and  similarly
  for "array of unknown bound of T" [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''
   --end example]

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 multidimen­
  sional array is created; the constant  expressions  that  specify  the
  bounds  of  the arrays can be omitted only for the first member of the
  sequence.  [Note: this elision is useful for  function  parameters  of
  array  types, and when the array is external and the definition, which
  allocates  storage,  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 [Example:
          float fa[17], *afp[17];
  declares an array of float numbers and an array of pointers  to  float
  numbers.  For another example,
          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 [Note:  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,
  2) The enumeration types are included in the fundamental types.

  subscripting 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
  pointed-to  (n-1)-dimensional  array, which itself is immediately con­
  verted into a pointer.

8 [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 [Note: it follows from all this that arrays in C++ are stored row-wise
  (last subscript varies fastest) and that the first  subscript  in  the
  declaration 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 exception-specificationopt
  and the type of the contained declarator-id in the declaration T D1 is
  "derived-declarator-type-list  T,"  the type of the declarator-id in D
  is  "derived-declarator-type-list  cv-qualifier-seqopt  function  with
  parameters  of  type  parameter-declaration-clause and returning T"; a
  type of this form is a function type3).
                  parameter-declaration-listopt ...opt
                  parameter-declaration-list , ...
                  parameter-declaration-list , parameter-declaration
                  decl-specifier-seq declarator
                  decl-specifier-seq declarator = assignment-expression
                  decl-specifier-seq abstract-declaratoropt
                  decl-specifier-seq abstract-declaratoropt = assignment-expression

  3) As indicated by the syntax, cv-qualifiers are a significant  compo­
  nent in function return types.

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 shall be equal to or greater than the number  of  parame­
  ters  specified; if it is empty, the function takes no arguments.  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 syntacti­
  cally  correct, ", ..." is synonymous with "...".  [Note: 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,  sev­
  eral transformations take place upon the types.  Any cv-qualifier mod­
  ifying 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.  The return type and the parameter
  type list, but not the default arguments (_dcl.fct.default_) or excep­
  tion specification (_except.spec_), 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  member  function; see _class.this_.  It is part of the
  function type.

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

  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 sequence of "pointer to" and "array of" derived declarator  types.
  This exclusion applies to the parameters of the function, and if a pa­
  rameter is a pointer to function or pointer to member function then to
  its parameters also, etc.

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

6 [Note:  the  parameter-declaration-clause is used to check and convert
  arguments in calls and  to  check  pointer-to-function,  reference-to-
  function,  and  pointer-to-member-function assignments and initializa­
  tions.  ]

7 An identifier can optionally be provided as a parameter name; if  pre­
  sent  in  a  function definition (_dcl.fct.def_), it names a parameter
  (sometimes called "formal argument").  [Note: in particular, parameter
  names  are  also optional in function definitions and names used for a
  parameter in different declarations and the definition of  a  function
  need  not be the same.  If an identifier is present in a function dec­
  laration, it cannot be used since it goes out of scope at the  end  of
  the function declarator (_basic.scope_); ]

8 [Note: The exception-specification is described in _except.spec_ .  ]

9 [Example: the declaration
          int i,
              (*pif)(const char*, const char*);
  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.

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

11The declaration
          int fseek(FILE*, long, int);
  declares a function taking three arguments of the specified types, and
  returning int (_dcl.type_).  The declaration
          int printf(const char*, ...);
  declares a function that can be called with varying numbers and  types
  of arguments.
          printf("hello world");
          printf("a=%d b=%d", a, b);

  However, the first argument must be of a type that can be converted to
  a const char*.

12 --end example]

  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 [Example: the declaration
          void 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)

4 For non-template functions, default arguments can be  added  in  later
  declarations of a function in the same scope.  Declarations in differ­
  ent 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).  [Example:
          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

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

          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)
   --end example] Declarations of a given nonmember function in  differ­
  ent  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 accumu­
  lated sets of default arguments at the end of  the  translation  units
  shall be the same).

5 Default  argument  expressions  have their names bound and their types
  checked at the point of declaration.  [Example: in the following code,
  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))
   --end example]

6 In member function declarations, names in default argument expressions
  are looked up in the scope of the class like names in member  function
  bodies  (_class.scope0_).   The  default  arguments  in an out-of-line
  function definition are added to the set of default arguments provided
  by the member function declaration in the class definition.  [Example:
          class C {
                  void f(int i = 3);
                  void g(int i, int j = 99);
          void C::f(int i = 3) // error: default argument already
          { }                  // specified in class scope
          void C::g(int i = 88, int j) // in this translation unit,
          { }                          // C::g can be called with no argument
   --end example]

7 Local variables shall not be used  in  default  argument  expressions.

          void f()
              int i;
              extern void g(int x = i);   // error
              // ...
   --end example]

8 The  keyword  this shall not be used in a default argument of a member
  function.  [Example:
          class A {
              void f(A* p = this) { }     // error
   --end example]

9 Default arguments are evaluated at each point  of  call  before  entry
  into  a  function.   The  order of evaluation of function arguments is
  implementation-defined.  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  argu­
  ment  expression  are in scope and can hide namespace and class member
  names.  [Example:
          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: parameter `I' found
          int h(int a, int b = sizeof(a));  // error, parameter `a' used
                                            // in default argument
   --end example] 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_)  or  unless  it  is  used  to  form  a  pointer to member
  (_expr.unary.op_).  [Example: the declaration of X::mem1() in the fol­
  lowing  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;
              int mem1(int i = a); // error: nonstatic member `a'
                                   // used as default argument
              int 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_.  ] A default argument is not part of
  the type of a function.  [Example:

          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
    --end example] When a declaration of a function is introduced by way
  of a  using  declaration  (_namespace.udecl_),  any  default  argument
  information associated with the declaration is imported as well.

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.  [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()
   --end example]

  8.4  Function definitions                                [dcl.fct.def]

1 Function definitions have the form
                  decl-specifier-seqopt declarator ctor-initializeropt function-body
                  decl-specifier-seqopt declarator function-try-block

  The declarator in a function-definition shall have the form
          D1 ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
  as described in _dcl.fct_.  A function shall be defined only in names­
  pace or class scope.

2 The parameters are in the scope of the outermost block  of  the  func­

3 [Example: 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

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: unused parameters need not be named.  For example,
          void print(int a, int)
              printf("a = %d\n",a);
   --end note]

  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-clause
                  ( expression-list )
                  { initializer-list ,opt }
                  { }
                  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.  [Example:
          int f(int);
          int a = 2;
          int b = f(a);
          int c(b);
   --end example]

3 [Note:   default   argument   expressions  are  more  restricted;  see

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

5 To zero-initialize storage for an object of type T means:

  --if  T  is  a scalar or pointer-to-member type, the storage is set to
    the value of 0 (zero) converted to T;

  --if T is a non-union class type, the storage for each nonstatic  data
    member and each base-class subobject is zero-initialized;

  --if  T is a union type, the storage for its first nonstatic data mem­
    ber is zero-initialized;

  --if T is an array  type,  the  storage  for  each  element  is  zero-

  --if T is a reference type, no initialization is performed.

  To default-initialize an object of type T means:

  --if  T  is  a  non-POD  class  type, the default constructor for T is
    called (and the initialization is ill-formed if T has no  accessible
    default constructor);

  --if T is an array type, each element is default-initialized;

  --otherwise, the storage for the object is zero-initialized.

  Default-initialization   uses   the   direct-initialization  semantics
  described below.

6 The memory occupied by any object of static storage duration shall  be
  zero-initialized.  Furthermore, if no initializer is explicitly speci­
  fied in the declaration of the object and the  object  is  of  non-POD
  class  type  (or  array thereof), then default initialization shall be
  performed.  If no initializer is specified for an  object  with  auto­
  matic  or  dynamic storage duration, the object and its subobjects, if
  any, have an indeterminate initial value.6)

7 An initializer for a static member is in the  scope  of  the  member's
  class.  [Example:

  6) This does not apply to aggregate objects with automatic storage du­
  ration initialized with an incomplete brace-enclosed initializer-list;
  see _dcl.init.aggr_.

          int a;

          struct X {
              static int a;
              static int b;

          int X::a = 1;
          int X::b = a;   // X::b = X::a
   --end example]

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

9 [Note: since () is not permitted by the syntax for 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.  The form () is per­
  mitted  in  certain   other   initialization   contexts   (_expr.new_,
  _expr.type.conv_, _class.base.init_).  ]

10The  initialization  that occurs in argument passing, function return,
  and brace-enclosed initializer lists (_dcl.init.aggr_) is called copy-
  initialization and 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 called direct-initialization and is  equivalent
  to the form
          T x(a);

11The 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

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

  --If the destination type is a (possibly cv-qualified) class type:

    --If the class is an aggregate (_dcl.init.aggr_), and  the  initial­
      izer is a brace-enclosed list, see _dcl.init.aggr_.

    --If  the initialization is direct-initialization, or if it is copy-

      initialization where the cv-unqualified version of the source type
      is the same class as, or a derived class of, the class of the des­
      tination, constructors are considered.  The  applicable  construc­
      tors  are enumerated (_over.match.ctor_), and the best one is cho­
      sen through overload resolution (_over.match_).   The  constructor
      so  selected is called to initialize the object, with the initial­
      izer expression(s) as its argument(s).  If no constructor applies,
      or  the  overload  resolution  is ambiguous, the initialization is

    --Otherwise (i.e., for the remaining copy-initialization  cases),  a
      temporary  of  the destination type is created.  User-defined con­
      versions that can convert from the source type to the  destination
      type  are enumerated (_over.match.user_), and the best one is cho­
      sen through overload resolution (_over.match_).  The  user-defined
      conversion  so  selected  is  called  to  convert  the initializer
      expression into the temporary.  If the conversion cannot  be  done
      or  is  ambiguous,  the  initialization is ill-formed.  The object
      being initialized is then direct-initialized  from  the  temporary
      according  to  the rules above.7) In certain cases, an implementa­
      tion is permitted to eliminate the temporary by  initializing  the
      object directly; see _class.temporary_.

  --Otherwise,  if  the  source  type is a (possibly cv-qualified) class
    type, conversion functions are considered.  The  applicable  conver­
    sion  functions 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 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 cv-unqualified version of the des­
    tination  type;  no user-defined conversions are considered.  If the
    conversion cannot be done, the initialization is ill-formed.  [Note:
    an  expression of type "cv1 T" can initialize an object of type "cv2
    T" independently of the cv-qualifiers cv1 and cv2.
              int a;
              const int b = a;
              int c = b;
     --end note]

12If T is a scalar type, then a declaration of the form
          T x = { a };
  is equivalent to
          T x = a;

  7)  Because  the  type of the temporary is the same as the type of the
  object being initialized, this direct-initialization, if  well-formed,
  will use a copy constructor (_class.copy_) to copy the temporary.

  8.5.1  Aggregates                                      [dcl.init.aggr]

1 An aggregate is an array or a class (_class_)  with  no  user-declared
  constructors  (_class.ctor_),  no private or protected non-static data
  members (_class.access_), no non-static members of reference type,  no
  non-static  const  members,  no base classes (_class.derived_), and no
  virtual functions (_class.virtual_).8)

2 When an aggregate is initialized the initializer can  be  an  initial­
  izer-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.
          struct A {
                  int x;
                  struct B {
                          int i;
                          int j;
                  } b;
          } a = { 1, { 2, 3 } };
  initializes a.x with 1, a.b.i with 2, a.b.j with 3.  ]

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

4 An array of unknown size initialized with  a  brace-enclosed  initial­
  izer-list  containing  n  initializers,  where n shall be greater than
  zero, is defined as having n elements (_dcl.array_).  [Example:
          int x[] = { 1, 3, 5 };
  declares and initializes x as a one-dimensional array that  has  three
  elements since no size was specified and there are three initializers.
  ] An empty initializer list {} shall not be used  as  the  initializer
  for an array of unknown bound.8)

5 Static data members are not considered members of the class  for  pur­
  poses of aggregate initialization.  [Example:
          struct A {
                  int i;
                  static int s;
                  int j;
          } a = { 1, 2 };
  Here, the second initializer 2 initializes a.j and not the static data
  member A::s.  ]

6 An initializer-list  is  ill-formed  if  the  number  of  initializers
  exceeds the number of members or elements to initialize.  [Example:
          char cv[4] = { 'a', 's', 'd', 'f', 0 };  // error
  is ill-formed.  ]

  8)  The  syntax  provides for empty initializer-lists, but nonetheless
  C++ does not have zero length arrays.

7 If  there are fewer initializers in the list than there are members in
  the aggregate, then each member not explicitly  initialized  shall  be
  initialized  with  a value of the form T() (_expr.type.conv_), where T
  represents the type of the uninitialized member.  [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 the value  of
  an expression of the form int(), that is, 0.  ]

8 An  initializer  for  an aggregate member that is an empty class shall
  have the form of an empty initializer-list {}.  [Example:
          struct S { };
          struct A {
                  S s;
                  int i;
          } a = { { } , 3 };
   --end example] An empty initializer-list can be  used  to  initialize
  any aggregate.  If the aggregate is not an empty class, then each mem­
  ber of the aggregate shall be initialized with a value of the form T()
  (_expr.type.conv_),  where  T represents the type of the uninitialized

9 When initializing a multi-dimensional array, the initializers initial­
  ize  the elements with the last (rightmost) index of the array varying
  the fastest (_dcl.array_).  [Example:
          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.  ]

10Braces  can  be elided in an initializer-list as follows.  If the ini­
  tializer-list begins with a left brace,  then  the  succeeding  comma-
  separated  list of initializers initializes the members of a subaggre­
  gate; it is erroneous for there to be more initializers than  members.
  If,  however,  the  initializer-list for a subaggregate does not begin
  with a left brace, then only enough initializers  from  the  list  are
  taken  to  initialize  the  members of the subaggregate; any remaining
  initializers are left to initialize the next member of  the  aggregate
  of which the current subaggregate is a member.  [Example:
          float y[4][3] = {
              { 1, 3, 5 },
              { 2, 4, 6 },
              { 3, 5, 7 },
  is  a  completely-braced  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]'s elements are initialized as if explic­
  itly  initialized with an expression of the form float(), that is, are
  initialized with 0.0.  In the following example, braces  in  the  ini­
  tializer-list  are  elided;  however the initializer-list has the same
  effect as the completely-braced initializer-list of the above example,

          float y[4][3] = {
              1, 3, 5, 2, 4, 6, 3, 5, 7
  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].   --end exam­

11All type conversions (_over.match.user_) are considered when  initial­
  izing  the  aggregate  member with an initializer from an initializer-
  list.  If the initializer can initialize a member, the member is  ini­
  tialized.   Otherwise,  if  the member is itself a non-empty subaggre­
  gate, brace elision is assumed and the initializer is  considered  for
  the initialization of the first member of the subaggregate.  [Example:
          struct A {
              int i;
              operator int();
          struct B {
                  A a1, a2;
                  int z;
          A a;
          B b = { 4, a, a };
  Braces are elided around the initializer for b.a1.i.  b.a1.i  is  ini­
  tialized  with  4, b.a2 is initialized with a, b.z is initialized with
  whatever a.operator int() returns.  ]

12[Note: An aggregate array or an aggregate class may contain members of
  a  class  type  with a user-declared constructor (_class.ctor_).  Ini­
  tialization   of   these   aggregate   objects   is    described    in
  _class.expl.init_.  ]

13When  an  aggregate  is initialized with a brace-enclosed initializer-
  list, if some members are initialized with  constant  expressions  and
  other  members  are  initialized  with non-constant expressions, it is
  unspecified  whether  the  initialization  of  members  with  constant
  expressions  takes place during the static phase or during the dynamic
  phase of initialization (_basic.start.init_).

14The 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.  [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
   --end example]

  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 string
  literal; successive characters of the string initialize the members of
  the array.  [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.
          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.  [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]'
   --end example]

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.
          int& r1;         // error: initializer missing
          extern int& r2;  // ok
   --end example]

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 rela­
  tionship 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 binding is ill-formed if T1 is an inaccessible (_class.access_)
  or ambiguous (_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

    --"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, 9) then

7   the reference  is  bound  directly  to  the  initializer  expression
    lvalue.   [Note: the usual lvalue-to-rvalue (_conv.lval_), array-to-
    pointer (_conv.array_), and function-to-pointer (_conv.func_)  stan­
    dard  conversions are not needed, and therefore are suppressed, when
    such direct bindings to lvalues are done.  ] [Example:
              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'
     --end example]

  --Otherwise, the reference shall  be  to  a  non-volatile  const  type
    (i.e., cv1 shall be const).  [Example:
              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
     --end example]
  9)  This requires a conversion function (_class.conv.fct_) returning a
  reference type, and therefore applies only when T2 is a class type.

    --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 implementa­

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

9     The appropriate copy constructor must be callable whether  or  not
      the copy is actually done.  [Example:
                  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
       --end example]

    --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.  [Example:
                  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
       --end example]

11  [Note: _class.temporary_ describes the lifetime of temporaries bound
    to references.  ]

  10)  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 infi­
  nite recursion.