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  may  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
  or new, the name of a type must 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-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.  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

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

  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 {
          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
          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 may 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 = 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;
  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;
  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 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  must  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 must 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 {
              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

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

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
  pointed-to  (n-1)-dimensional  array,  which  itself  is   immediately
  2) The enumeration types are included in the fundamental types.

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

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 may not be a  parameter  type
  (though types derived from void, such as void*, may).  Where syntacti­
  cally correct, , ...  is synonymous with  ....   The  standard  header
  3)  As indicated by the syntax, cv-qualifiers are a significant compo­
  nent in function return types.

  <stdarg.h>  contains  a mechanism for accessing arguments passed using
  the ellipsis, see _lib.headers_.

  +-------                      BEGIN BOX 1                     -------+
  Something should probably be said about how  ...   arguments  work  in
  C++.   For example, do they work for member functions?  Virtual member
  functions?  If so, what are the rules?
  +-------                       END BOX 1                      -------+

  See _class.ctor_ for the treatment of array arguments.

3 A single name may 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 must 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 2                     -------+
  Issue: a definition for signature will be added as soon as the  seman­
  tics are made precise.
  +-------                       END BOX 2                      -------+

  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 may be arrays of pointers to functions.
  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.

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

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,
              (*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.

9 Typedefs are sometimes convenient when the return type of  a  function
  is  complex.   For  example,  the  function fpif above could have been
          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 must 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.  All subsequent parameters must
  have default arguments supplied in this or  previous  declarations  of
  this function.  Default arguments will be used in calls where trailing
  arguments are missing.  A default argument shall not be redefined by a
  later declaration (not even to the same value).  A declaration may add
  default arguments, however, not given in previous declarations.

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 may 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),

3 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(2):
          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
              // ...

4 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  may  not  be
  used  in  default  argument  expressions.   Parameters  of  a function
  declared before a default argument expression are  in  scope  and  may
  hide namespace and class member names.  For 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: `float' called

5 Similarly,  the  declaration  of X::mem1() in the following example is
  undefined 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_.

6 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

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

  8.4  Function definitions                                [dcl.fct.def]

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

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

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

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

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 may 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
  may  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 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;

4 Default    argument    expressions    are    more    restricted;   see

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

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

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

8 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
  See _dcl.fct.default_ for initializers used as default arguments.

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

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

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

  +-------                      BEGIN BOX 3                     -------+
  Revise  _class.expl.init_ (12.6.1) to reference this.

  +-------                       END BOX 3                      -------+

  --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 destination type; no  user-defined
    conversions  are  considered.  If the conversion cannot be done, the
    initialization is ill-formed.

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

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

  5) The syntax provides for empty initializer clauses, but  nonetheless
  C++ does not have zero length arrays.

          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.

7 Initialization  of  arrays  of objects of a class with constructors is
  described in _class.expl.init_.

8 The initializer for a union with no constructor  is  either  a  single
  expression  of  the same type, or a brace-enclosed initializer 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 may not be more initializers than there are members or  elements
  to initialize.  For example,
          char cv[4] = { 'a', 's', 'd', 'f', 0 };  // error
  is ill-formed.

10A  POD-struct6) is an aggregate structure that contains neither refer­
  ences nor pointers to members.  Similarly, a POD-union is an aggregate
  union that contains neither references nor pointers to members.

  6) The acronym POD stands for plain ol' data.

  8.5.2  Character arrays                              [dcl.init.string]

1 A  char array (whether plan char, signed, or unsigned) can be initial­
  ized by a string; a wchar_t  array  may  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 may not be more initializers than there are array elements.  For
          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_), must 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 may 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
          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 an accessible unambiguous base
  class of T2.  cv1 T1 is reference-compatible with cv2 T2 if T1 is ref­
  erence-related  to  T2  and  cv1  is  the same cv-qualification as, or

  greater cv-qualification than, cv2.  For purposes of overload  resolu­
  tion,  cases  for  which  cv1 is greater cv-qualification than cv2 are
  identified  as  reference-compatible  with  added  qualification  (see

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

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

  --Otherwise, the reference must be to a const  type  (i.e.,  cv1  must
    include const qualification); if not, the program is ill-formed.

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

      --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)
  7)  This requires a conversion function (_class.conv.fct_) returning a
  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­

7     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

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

                  const volatile int cvi = 1;
                  const int& r = cvi;     // error: type qualifiers dropped

8   The lifetime of a temporary object bound to a reference or  contain­
    ing a sub-object that is bound to a reference is the lifetime of the
    reference itself (_basic.stc.ref_).