______________________________________________________________________

  8   Declarators                                             [dcl.decl]

  ______________________________________________________________________

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

2 The  two  components  of a declaration are the specifiers (decl-speci-
  fier-seq; _dcl.spec_) and the declarators (init-declarator-list).  The
  specifiers indicate the type, storage class or other properties of the
  objects, functions or typedefs being declared.  The declarators  spec-
  ify  the  names  of these objects, functions or typedefs, and (option-
  ally) modify the type of the  specifiers  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)

  _________________________
  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  a  name  introduced by one of the declarators
  hides a type name used by the dcl-specifiers, so that  when  the  same
  dcl-specifiers  are used in a subsequent declaration, they do not have
  the same meaning, 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

4 Declarators have the syntax
          declarator:
                  direct-declarator
                  ptr-operator declarator
          direct-declarator:
                  declarator-id
                  direct-declarator ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
                  direct-declarator [ constant-expressionopt ]
                  ( declarator )
          ptr-operator:
                  * cv-qualifier-seqopt
                  &
                  ::opt nested-name-specifier * cv-qualifier-seqopt
          cv-qualifier-seq:
                  cv-qualifier cv-qualifier-seqopt
          cv-qualifier:
                  const
                  volatile
          declarator-id:
                  ::opt id-expression
                  ::opt 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
  function.
          type-id:
                  type-specifier-seq abstract-declaratoropt
          type-specifier-seq:
                  type-specifier type-specifier-seqopt
          abstract-declarator:
                  ptr-operator abstract-declaratoropt
                  direct-abstract-declarator
          direct-abstract-declarator:
                  direct-abstract-declaratoropt ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
                  direct-abstract-declaratoropt [ constant-expressionopt ]
                  ( abstract-declarator )
  It is possible to identify uniquely  the  location  in  the  abstract-
  declarator  where the identifier would appear if the construction were
  a declarator in a declaration.  The named type is then the same as the
  type of the hypothetical identifier.  [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  int,"  "pointer  to  int," "array of 3

  pointers to int," "pointer to array of 3 int," "function of (no param-
  eters)  returning  pointer to int," and "pointer to a function of dou-
  ble) returning int.''  ]

2 A type can also be named  (often  more  easily)  by  using  a  typedef
  (_dcl.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, the choice is 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   the   ambiguities   mentioned   in
  _stmt.ambig_,  the  resolution is to consider any construct that could
  possibly be a declaration a declaration.  [Note: a declaration can  be
  explicitly  disambiguated by a nonfunction-style cast, by a = to indi-
  cate initialization or by removing the  redundant  parentheses  around
  the parameter name.  ] [Example:
          struct S {
              S(int);
          };
          void foo(double a)
          {
              S w(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  different  contexts.   The  ambiguity
  appears  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()  {
                  const int x = 63;
                  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]

7 Another ambiguity arises in a parameter-declaration-clause of a  func-
  tion  declaration,  or in a type-id that is the operand of a sizeof or
  typeid operator, when a type-name is nested in parentheses.   In  this
  case,  the  choice  is  between the declaration of a parameter of type
  pointer to function and the declaration of a parameter with  redundant
  parentheses  around  the declarator-id.  The resolution is to consider
  the type-name as a simple-type-specifier rather than a  declarator-id.
  [Example:
          class C { };
          void f(int(C)) { } // void f(int (*fp)(C c)) { }
                             // not: void f(int C);

          int g(C);

          void foo() {
                  f(1);    // error: cannot convert 1 to function ptr
                  f(g);    // OK
          }
  For another example,
          class C { };
          void h(int *(C[10]));  // void h(int *(*_fp)(C _parm[10]));
                                 // not: void h(int *C[10]);
   --end example]

  8.3  Meaning of declarators                              [dcl.meaning]

1 A list of declarators appears after an optional (_dcl.dcl_) decl-spec-
  ifier-seq (_dcl.spec_).  Each declarator contains exactly one declara-
  tor-id;  it  names the identifier that is declared.  The id-expression
  of a declarator-id shall be a simple identifier except for the  decla-
  ration   of   some   special  functions  (_class.conv_,  _class.dtor_,
  _over.oper_) and for the declaration of  template  specializations  or

  partial  specializations  (_temp.spec_).  A declarator-id shall not be
  qualified  except  for   the   definition   of   a   member   function
  (_class.mfct_)  or static data member (_class.static_) or nested class
  (_class.nest_) outside  of  its  class,  the  definition  or  explicit
  instantiation  of  a function, variable or class member of a namespace
  outside of its namespace, or the definition of a  previously  declared
  explicit  specialization  outside of its namespace, or the declaration
  of a friend function that is a member of another  class  or  namespace
  (_class.friend_).   When  the declarator-id is qualified, the declara-
  tion shall refer to a previously  declared  member  of  the  class  or
  namespace to which the qualifier refers, and the member shall not have
  been introduced by a using-declaration in the scope of  the  class  or
  namespace nominated by the nested-name-specifier of the declarator-id.
  [Note: if the qualifier is the global ::  scope  resolution  operator,
  the  declarator-id  refers  to a name declared in the global namespace
  scope.  ] In the qualified declarator-id for a class or namespace mem-
  ber  definition  that  appears outside of the member's class or names-
  pace, the nested-name-specifier shall not name any of  the  namespaces
  that enclose the member's definition.  [Example:
          namespace A {
                  struct B {
                          void f();
                  };
                  void A::B::f() { } // ill-formed: the declarator must not be
                                     // qualified with A::
          }
   --end example]

2 An  auto,  static, extern, register, mutable, 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.

3 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
  subclauses  give a recursive procedure for determining the type speci-
  fied for the contained declarator-id by such a declaration.

4 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
  declaration
          int unsigned i;
  the  type  specifiers  int  unsigned  determine the type unsigned int"
  (_dcl.type.simple_).  ]

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

6 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++;
          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-unquali-
  fied 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 See also _expr.ass_ and _dcl.init_.

4 [Note: there are no pointers to references; see _dcl.ref_.  Since  the
  address  of  a  bit-field (_class.bit_) cannot be taken, a pointer can
  never point to a bit-field.  ]

  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."   Cv-qualified  refer-
  ences  are  ill-formed  except  when  the cv-qualifiers are introduced
  through the use of a typedef (_dcl.typedef_) or  of  a  template  type
  argument  (_temp.arg_),  in  which case the cv-qualifiers are ignored.
  [Example: in
          typedef int& A;
          const A aref = 3; // ill-formed;
                            // non-const reference initialized with rvalue
  the type of aref is "reference to int", not "const reference to  int".
  ]  [Note:  a  reference can be thought of as a name of an object.  ] A
  declarator that specifies the type "reference  to  cv  void"  is  ill-
  formed.

2 [Example:
          void f(double& a) { a += 3.14; }
          // ...
          double d = 0;
          f(d);
  declares  a to be a reference parameter of f so the call f(d) will add
  3.14 to d.
          int v[20];
          // ...
          int& g(int i) { return v[i]; }
          // ...
          g(3) = 7;
  declares the function g() to return  a  reference  to  an  integer  so
  g(3)=7  will  assign  7  to  the  fourth  element of the array v.  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;
                  h(q);
          }
  declares p to be a reference to a pointer to link so h(q) will leave q
  with the value zero.  See also _dcl.init.ref_.  ]

3 It  is  unspecified  whether  or  not  a  reference  requires  storage
  (_basic.stc_).

4 There shall be no references to references, no arrays  of  references,
  and  no  pointers to references.  The declaration of a reference shall
  contain an initializer (_dcl.init.ref_) except  when  the  declaration
  contains  an  explicit extern specifier (_dcl.stc_), is a class member
  (_class.mem_) declaration within a class declaration, or is the decla-
  ration  of  a parameter or a return type (_dcl.fct_); see _basic.def_.
  A reference shall be initialized to refer to a valid object  or  func-
  tion.   [Note: in particular, a null reference cannot exist in a well-
  defined program, because the only way to create such a reference would
  be  to  bind  it  to  the  "object"  obtained  by dereferencing a null
  pointer,  which  causes   undefined   behavior.    As   described   in
  _class.bit_, a reference cannot be bound directly to a bit-field.  ]

  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 {
          public:
              void f(int);
              int a;
          };
          class Y;

          int X::* pmi = &X::a;
          void (X::* pmf)(int) = &X::f;
          double X::* pmd;
          char Y::* pmc;
  declares  pmi,  pmf,  pmd  and pmc to be a pointer to a member of X of
  type int, a pointer to a member of X of type void(int), a pointer to a
  member of X of type double and a pointer to a member of Y of type char
  respectively.  The declaration of pmd is well-formed even though X has
  no members of type double.  Similarly, the declaration of pmc is well-
  formed even though Y is an incomplete type.  pmi and pmf can  be  used
  like this:
          X obj;
          //...
          obj.*pmi = 7;   // assign 7 to an integer
                          // member of obj
          (obj.*pmf)(7);  // call a function member of obj
                          // with the argument 7
   --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:
  see also _expr.unary_ and _expr.mptr.oper_.  The type "pointer to mem-
  ber" is distinct from the type "pointer", that is, a pointer to member
  is declared only by the pointer to member declarator syntax, and never
  by the pointer declarator syntax.  There is  no  "reference-to-member"
  type in C++.  ]

  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 is called the array element type; this type shall not
  be a reference type, the type void, a function  type  or  an  abstract
  class  type.  If the constant-expression (_expr.const_) is present, it
  shall be an integral  constant  expression  and  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."  An object of array type contains a contiguously allocated non-
  empty set of N sub-objects of type T.  If the constant  expression  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_.  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];
          typedef const A CA;     // type is ``array of 5 const int''
          typedef const AA CAA;   // type is ``array of 2 array of 3 const int''
   --end example] [Note: an "array of N cv-qualifier-seq T" has cv-qual-
  ified type; such an  array  has  internal  linkage  unless  explicitly
  declared  extern  (_dcl.type.cv_) and must be initialized as specified
  in _dcl.init_.  ]

2 An array can be constructed from one of the fundamental types  (except
  void), from a pointer, from a pointer to member, from a class, from an
  enumeration type, 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-expres-
  sion can also be omitted when the declarator is followed  by  an  ini-
  tializer  (_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,  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  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  function of (parameter-declaration-
  clause) cv-qualifier-seqopt returning T"; a type of  this  form  is  a
  function type2).
          parameter-declaration-clause:
                  parameter-declaration-listopt ...opt
                  parameter-declaration-list , ...
          parameter-declaration-list:
                  parameter-declaration
                  parameter-declaration-list , parameter-declaration
          parameter-declaration:
                  decl-specifier-seq declarator
                  decl-specifier-seq declarator = assignment-expression
                  decl-specifier-seq abstract-declaratoropt
                  decl-specifier-seq abstract-declaratoropt = assignment-expression

2 The parameter-declaration-clause determines the arguments that can  be
  specified,  and their processing, when the function is called.  [Note:
  the parameter-declaration-clause is  used  to  convert  the  arguments
  specified  on the function call; see _expr.call_.  ] If the parameter-
  declaration-clause 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).  If the parame-
  ter-declaration-clause terminates with  an  ellipsis,  the  number  of
  arguments  shall  be equal to or greater than the number of parameters
  specified.  Where syntactically correct, ", ..."  is  synonymous  with
  "...".  [Example: 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*.   ]  [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 a function is determined using the follow-
  ing  rules.   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  these  types  to  determine  the
  function  type.   Any  cv-qualifier  modifying  a  parameter  type  is
  _________________________
  2)  As indicated by the syntax, cv-qualifiers are a significant compo-
  nent in function return types.

  deleted; e.g., the type void(const int) becomes void(int).   Such  cv-
  qualifiers only affect the definition of the parameter within the body
  of the function; they do not affect the function type.  If a  storage-
  class-specifier  modifies  a parameter type, the specifier is deleted;
  e.g., register char*  becomes  char*.   Such  storage-class-specifiers
  affect  only  the  definition  of the parameter within the body of the
  function; they do not affect the function type.  The resulting list of
  transformed  parameter types is the function's parameter type list.  A
  cv-qualifier-seq shall only be part of the function type  for  a  non-
  static member function, the function type to which a pointer to member
  refers, or the top-level function type of a function typedef  declara-
  tion.   The  effect  of a cv-qualifier-seq in a function declarator is
  not the same as adding cv-qualification on top of the  function  type,
  i.e., it does not create a cv-qualified function type.  In fact, if at
  any time in the determination of a type a cv-qualified  function  type
  is formed, the program is ill-formed.  [Example:
          typedef void F();
          struct S {
                  const F f; // ill-formed:
                             // not equivalent to: void f() const;
          };
    --end  example] The return type, the parameter type list and the cv-
  qualifier-seq, but not the default  arguments  (_dcl.fct.default_)  or
  the  exception specification (_except.spec_), are part of the function
  type.  [Note: function types are checked during  the  assignments  and
  initializations  of  pointer-to-functions, reference-to-functions, and
  pointer-to-member-functions.  ]

4 [Example: the declaration
          int fseek(FILE*, long, int);
  declares a function taking three arguments of the specified types, and
  returning int (_dcl.type_).  ]

5 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.3) Functions shall not have a  return
  type  of  type array or function, although they may have a return type
  of type pointer or reference to such things.  There shall be no arrays
  of  functions,  although there can be arrays of pointers to functions.
  Types shall not be defined in return or parameter types.  The type  of
  a  parameter or the return type for a function declaration that is not
  a definition may be an incomplete class type.

6 A typedef of function type may be used to declare a function but shall
  not be used to define a function (_dcl.fct.def_).  [Example:

  _________________________
  3)  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.

          typedef void F();
          F  fv;    // ok: equivalent to void fv();
          F  fv { } // ill-formed
          void fv() { } // ok: definition of fv
   --end example] A typedef of a function type whose declarator includes
  a cv-qualifier-seq shall be used only to declare the function type for
  a  nonstatic  member function, to declare the function type to which a
  pointer to member refers, or to declare the top-level function type of
  another function typedef declaration.  [Example:
          typedef int FIC(int) const;
          FIC f;         // ill-formed: does not declare a member function
          struct S {
                  FIC f; //ok
          };
          FIC S::*pm = &S::f; // ok
   --end example]

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 a parameter name is present  in  a  function
  declaration that is not a definition, it cannot be used outside of the
  parameter-declaration-clause since it goes out of scope at the end  of
  the function declarator (_basic.scope_).  ]

8 [Example: the declaration
          int i,
              *pi,
              f(),
              *fpi(int),
              (*pif)(const char*, const char*);
              (*fpif(int))(int);
  declares an integer i, a pointer pi to an integer, a function f taking
  no arguments and returning an integer, a function fpi taking an  inte-
  ger argument and returning a pointer to an integer, a pointer pif to a
  function which takes two pointers to constant characters  and  returns
  an integer, a function fpif taking an integer argument and returning a
  pointer to a function that takes an integer argument  and  returns  an
  integer.  It is especially useful to compare fpi and pif.  The binding
  of *fpi(int) is *(fpi(int)), so the declaration suggests, and the same
  construction in an expression requires, the calling of a function fpi,
  and then using indirection through the (pointer) result  to  yield  an
  integer.   In  the  declarator  (*pif)(const  char*, const char*), the
  extra parentheses are necessary to indicate that indirection through a
  pointer  to  a  function  yields  a function, which is then called.  ]
  [Note: typedefs are sometimes convenient when the  return  type  of  a
  function  is complex.  For example, the function fpif above could have
  been declared
          typedef int  IFUNC(int);
          IFUNC*  fpif(int);
   --end note]

  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-declara-
  tion-clause,  it  shall  not  occur  within  a declarator or abstract-
  declarator of a parameter-declaration.4)

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
          }

  _________________________
  4) 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] For a  given  inline  function  defined  in  different
  translation  units,  the  accumulated sets of default arguments at the
  end of the translation units shall be the same; see _basic.def.odr_.

5 A default argument expression is implicitly converted (_conv_) to  the
  parameter type.  The default argument expression has the same semantic
  constraints as the initializer expression in a declaration of a  vari-
  able  of  the  parameter type, using the copy-initialization semantics
  (_dcl.init_).  The names in the expression are bound, and the semantic
  constraints  are  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] [Note:  in  member  function  declarations,  names  in
  default   argument   expressions   are   looked  up  as  described  in
  _basic.lookup.unqual_.  Access checking applies to  names  in  default
  argument expressions as described in _class.access_.  ]

6 The  default  arguments  in  a member function definition that appears
  outside of the class definition are added to the set of default  argu-
  ments provided by the member function declaration in the class defini-
  tion.  [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.
  [Example:
          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 each time the function is called.  The
  order  of  evaluation  of  function  arguments is unspecified.  Conse-
  quently, parameters of a function shall not be used in  default  argu-
  ment  expressions,  even  if  they are not evaluated.  Parameters of a
  function declared before a default argument expression  are  in  scope
  and can hide namespace and class member names.  [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 int 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 made known as well.  If
  the function is redeclared thereafter in the namespace with additional
  default arguments, the additional arguments  are  also  known  at  any
  point  following  the  redeclaration where the using-declaration is in
  scope.

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->B::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
          function-definition:
                  decl-specifier-seqopt declarator ctor-initializeropt function-body
                  decl-specifier-seqopt declarator function-try-block

          function-body:
                  compound-statement
  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-
  tion-body.

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

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

6 [Note: 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:
                  = initializer-clause
                  ( expression-list )
          initializer-clause:
                  assignment-expression
                  { initializer-list ,opt }
                  { }
          initializer-list:
                  initializer-clause
                  initializer-list , initializer-clause

2 Automatic, register, static, and external variables of namespace scope
  can  be  initialized  by  arbitrary expressions involving literals 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
  _dcl.fct.default_.

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 type (_basic.types_), 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 data member5) is
    zero-initialized;

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

  --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 (_class_), the default constructor for
    T is called (and the initialization is ill-formed if T has no acces-
    sible default constructor);

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

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

  A program that calls for default-initialization of an entity of refer-
  ence type is ill-formed.  If T is a cv-qualified type, the cv-unquali-
  fied version of T is used for these definitions of zero-initialization
  and default-initialization.

6 The memory occupied by any object of static storage duration shall  be
  zero-initialized  at  program  startup before any other initialization
  takes place.  [Note: in some cases, additional initialization is  done
  later.  ]

7 An  object whose initializer is an empty set of parentheses, i.e., (),
  shall be default-initialized.

8 [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_).  ]

  _________________________
  5) This member must not be static, by virtue of  the  requirements  in
  _class.union_.

9 If  no  initializer  is  specified for an object, and the object is of
  (possibly cv-qualified) non-POD class type  (or  array  thereof),  the
  object  shall be default-initialized; if the object is of const-quali-
  fied type, the  underlying  class  type  shall  have  a  user-declared
  default constructor.  Otherwise, if no initializer is specified for an
  object, the object and its subobjects, if any, have  an  indeterminate
  initial  value6); if the object or any of its subobjects are of const-
  qualified type, the program is ill-formed.

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

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

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

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

12The initialization that occurs in argument passing,  function  return,
  throwing   an   exception   (_except.throw_),  handling  an  exception
  (_except.handle_),    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);

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

14The 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
  _________________________
  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_.

  parenthesized list of expressions.

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

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

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

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

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

    --Otherwise  (i.e.,  for the remaining copy-initialization cases), a
      temporary is created.  User-defined conversion sequences that  can
      convert  from the source type to the destination type or a derived
      class thereof are enumerated (_over.match.copy_), and the best one
      is  chosen  through overload resolution (_over.match_).  The user-
      defined conversion so selected is called to convert  the  initial-
      izer  expression into a temporary, whose type is the type returned
      by the call of the user-defined conversion function, with the  cv-
      qualifiers  of  the destination type.  If the conversion cannot be
      done or is  ambiguous,  the  initialization  is  ill-formed.   The
      object  being initialized is then direct-initialized from the tem-
      porary according to the rules above.7) In certain cases, an imple-
      mentation 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.conv_), 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.
  _________________________
  7) Because the type of the temporary is the same as the  type  of  the
  object  being initialized, or is a derived class thereof, this direct-
  initialization,  if  well-formed,  will   use   a   copy   constructor
  (_class.copy_) to copy the temporary.

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

  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 base classes  (_class.derived_),  and  no
  virtual functions (_class.virtual_).

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

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

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

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

9 If  an  incomplete or empty initializer-list leaves a member of refer-
  ence type uninitialized, the program is ill-formed.

10When 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:
          int x[2][2] = { 3, 1, 4, 2 };
  initializes x[0][0] to 3, x[0][1] to 1, x[1][0] to 4, and  x[1][1]  to
  2.  On the other hand,
          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.  ]

11Braces can be elided in an initializer-list as follows.  If  the  ini-
  tializer-list begins with a left brace, then the succeeding comma-sep-
  arated list of initializers initializes the members of a subaggregate;
  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-
  ple]

12All  implicit type conversions (_conv_) are considered when initializ-
  ing the aggregate member with an initializer from an initializer-list.
  If the initializer can initialize a member, the member is initialized.
  Otherwise, if the member is itself  a  non-empty  subaggregate,  brace
  elision  is assumed and the initializer is considered for the initial-
  ization 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.  ]

13[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_.  ]

14When  an  aggregate with static storage duration is initialized with a
  brace-enclosed initializer-list, if all the member initializer expres-
  sions  are  constant expressions, and the aggregate is a POD type, the

  initialization shall be done during the static phase of initialization
  (_basic.start.init_);  otherwise,  it  is unspecified whether the ini-
  tialization of members with constant expressions  takes  place  during
  the static phase or during the dynamic phase of initialization.

15When  a  union  is  initialized with a brace-enclosed initializer, the
  braces shall only contain an initializer 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] [Note: as described above, the braces around the ini-
  tializer for a union member can be omitted if the union is a member of
  another aggregate.  ]

  8.5.2  Character arrays                              [dcl.init.string]

1 A  char  array (whether plain char, signed char, or unsigned char) can
  be initialized by a string-literal; a wchar_t array can be initialized
  by  a wide string-literal; successive characters of the string-literal
  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-
  literal.   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.
  [Example:
          char cv[4] = "asdf";  // error
  is  ill-formed  since there is no space for the implied trailing '\0'.
  ]

  8.5.3  References                                       [dcl.init.ref]

1 A variable declared to  be  a  T&,  that  is  "reference  to  type  T"
  (_dcl.ref_), shall be initialized by an object, or function, of type T
  or by an object that can be converted into a T.  [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.
  [Example:
          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

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

    --T2 is  a  class  type,  and  the  initializer  expression  can  be

      implicitly converted to an lvalue of type "cv3 T3," where "cv1 T1"
      is  reference-compatible  with  "cv3 T3"  9)  (this  conversion is
      selected  by  enumerating  the  applicable  conversion   functions
      (_over.match.ref_) and choosing the best one through overload res-
      olution (_over.match_)), then

7   the reference is bound directly to the initializer expression lvalue
    in  the  first case, and the reference is bound to the lvalue result
    of the conversion in the second case.  In this case the reference is
    said  to  bind  directly  to the initializer expression.  [Note: the
    usual     lvalue-to-rvalue      (_conv.lval_),      array-to-pointer
    (_conv.array_),  and function-to-pointer (_conv.func_) standard con-
    versions 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]

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

    --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-
      tion-defined):

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

      --A  temporary  of type "cv1 T2" [sic] is created, and a copy con-
        structor is called to copy the entire  rvalue  object  into  the
        temporary.  The reference is bound to the temporary or to a sub-
        object within the temporary.10)
  _________________________
  9) This requires a conversion function (_class.conv.fct_) returning  a
  reference type.
  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.

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]

10
    --Otherwise, a temporary of type "cv1 T1" is created and initialized
      from  the  initializer expression using the rules for a non-refer-
      ence copy 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.  ]