9 Declarations [dcl.dcl]

Declarations generally specify how names are to be interpreted.
Declarations have the form
declaration-seq:
	declaration
	declaration-seq declaration
declaration:
	block-declaration
	nodeclspec-function-declaration
	function-definition
	template-declaration
	deduction-guide
	explicit-instantiation
	explicit-specialization
	linkage-specification
	namespace-definition
	empty-declaration
	attribute-declaration
block-declaration:
	simple-declaration
	asm-definition
	namespace-alias-definition
	using-declaration
	using-directive
	static_assert-declaration
	alias-declaration
	opaque-enum-declaration
nodeclspec-function-declaration:
	attribute-specifier-seq declarator ;
alias-declaration:
	using identifier attribute-specifier-seq = defining-type-id ;
simple-declaration:
	decl-specifier-seq init-declarator-list ;
	attribute-specifier-seq decl-specifier-seq init-declarator-list ;
	attribute-specifier-seq decl-specifier-seq ref-qualifier [ identifier-list ] initializer ;
static_assert-declaration:
	static_assert ( constant-expression ) ;
	static_assert ( constant-expression , string-literal ) ;
empty-declaration:
	;
attribute-declaration:
	attribute-specifier-seq ;
[Note
:
asm-definitions are described in [dcl.asm], and linkage-specifications are described in [dcl.link]; function-definitions are described in [dcl.fct.def] and template-declarations and deduction-guides are described in [temp]; namespace-definitions are described in [namespace.def], using-declarations are described in [namespace.udecl] and using-directives are described in [namespace.udir].
end note
]
Attributes are described in [dcl.attr].
decl-specifiers, the principal components of a decl-specifier-seq, are described in [dcl.spec].
declarators, the components of an init-declarator-list, are described in [dcl.decl].
The attribute-specifier-seq appertains to each of the entities declared by the declarators of the init-declarator-list.
[Note
:
In the declaration for an entity, attributes appertaining to that entity may appear at the start of the declaration and after the declarator-id for that declaration.
end note
]
[Example
:
[[noreturn]] void f [[noreturn]] ();    // OK
end example
]
Except where otherwise specified, the meaning of an attribute-declaration is implementation-defined.
A declaration occurs in a scope; the scope rules are summarized in [basic.lookup].
A declaration that declares a function or defines a class, namespace, template, or function also has one or more scopes nested within it.
These nested scopes, in turn, can have declarations nested within them.
Unless otherwise stated, utterances in [dcl.dcl] about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are not nested within scopes nested within the declaration.
In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class or enumeration, that is, when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier with a class-key ([class.name]), or an enum-specifier.
In these cases and whenever a class-specifier or enum-specifier is present in the decl-specifier-seq, the identifiers in these specifiers are among the names being declared by the declaration (as class-names, enum-names, or enumerators, depending on the syntax).
In such cases, the decl-specifier-seq shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration.
[Example
:
enum { };           // ill-formed
typedef class { };  // ill-formed
end example
]
If the value of the expression when so converted is true, the declaration has no effect.
Otherwise, the program is ill-formed, and the resulting diagnostic message ([intro.compliance]) shall include the text of the string-literal, if one is supplied, except that characters not in the basic source character set are not required to appear in the diagnostic message.
[Example
:
static_assert(sizeof(int) == sizeof(void*), "wrong pointer size");
end example
]
An empty-declaration has no effect.
The decl-specifier-seq shall contain only the type-specifier auto and cv-qualifiers.
The initializer shall be of the form “= assignment-expression”, of the form “{ assignment-expression }”, or of the form “( assignment-expression )”, where the assignment-expression is of array or non-union class type.
Each init-declarator in the init-declarator-list contains exactly one declarator-id, which is the name declared by that init-declarator and hence one of the names declared by the declaration.
The defining-type-specifiers in the decl-specifier-seq and the recursive declarator structure of the init-declarator describe a type ([dcl.meaning]), which is then associated with the name being declared by the init-declarator.
If the decl-specifier-seq contains the typedef specifier, the declaration is called a typedef declaration and the name of each init-declarator is declared to be a typedef-name, synonymous with its associated type ([dcl.typedef]).
If the decl-specifier-seq contains no typedef specifier, the declaration is called a function declaration if the type associated with the name is a function type ([dcl.fct]) and an object declaration otherwise.
Syntactic components beyond those found in the general form of declaration are added to a function declaration to make a function-definition.
An object declaration, however, is also a definition unless it contains the extern specifier and has no initializer ([basic.def]).
A definition causes the appropriate amount of storage to be reserved and any appropriate initialization ([dcl.init]) to be done.
A nodeclspec-function-declaration shall declare a constructor, destructor, or conversion function.

9.1 Specifiers [dcl.spec]

The specifiers that can be used in a declaration are
decl-specifier:
	storage-class-specifier
	defining-type-specifier
	function-specifier
	friend
	typedef
	constexpr
	inline
decl-specifier-seq:
	decl-specifier attribute-specifier-seq
	decl-specifier decl-specifier-seq
The optional attribute-specifier-seq in a decl-specifier-seq appertains to the type determined by the preceding decl-specifiers ([dcl.meaning]).
The attribute-specifier-seq affects the type only for the declaration it appears in, not other declarations involving the same type.
Each decl-specifier shall appear at most once in a complete decl-specifier-seq, except that long may appear twice.
If a type-name is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous defining-type-specifier other than a cv-qualifier in the decl-specifier-seq.
The sequence shall be self-consistent as described below.
[Example
:
typedef char* Pc;
static Pc;                      // error: name missing
Here, the declaration static Pc is ill-formed because no name was specified for the static variable of type Pc.
To get a variable called Pc, a type-specifier (other than const or volatile) has to be present to indicate that the typedef-name Pc is the name being (re)declared, rather than being part of the decl-specifier sequence.
For another example,
void f(const Pc);               // void f(char* const) (not const char*)
void g(const int Pc);           // void g(const int)
end example
]
[Note
:
Since signed, unsigned, long, and short by default imply int, a type-name appearing after one of those specifiers is treated as the name being (re)declared.
[Example
:
void h(unsigned Pc);            // void h(unsigned int)
void k(unsigned int Pc);        // void k(unsigned int)
end example
]
end note
]

9.1.1 Storage class specifiers [dcl.stc]

The storage class specifiers are
storage-class-specifier:
	static
	thread_local
	extern
	mutable
At most one storage-class-specifier shall appear in a given decl-specifier-seq, except that thread_­local may appear with static or extern.
If thread_­local appears in any declaration of a variable it shall be present in all declarations of that entity.
If a storage-class-specifier appears in a decl-specifier-seq, there can be no typedef specifier in the same decl-specifier-seq and the init-declarator-list or member-declarator-list of the declaration shall not be empty (except for an anonymous union declared in a named namespace or in the global namespace, which shall be declared static ([class.union.anon])).
The storage-class-specifier applies to the name declared by each init-declarator in the list and not to any names declared by other specifiers.
A storage-class-specifier other than thread_­local shall not be specified in an explicit specialization or an explicit instantiation directive.
[Note
:
A variable declared without a storage-class-specifier at block scope or declared as a function parameter has automatic storage duration by default.
end note
]
The thread_­local specifier indicates that the named entity has thread storage duration.
It shall be applied only to the names of variables of namespace or block scope and to the names of static data members.
When thread_­local is applied to a variable of block scope the storage-class-specifier static is implied if no other storage-class-specifier appears in the decl-specifier-seq.
The static specifier can be applied only to names of variables and functions and to anonymous unions.
There can be no static function declarations within a block, nor any static function parameters.
A static specifier used in the declaration of a variable declares the variable to have static storage duration, unless accompanied by the thread_­local specifier, which declares the variable to have thread storage duration.
A static specifier can be used in declarations of class members; [class.static] describes its effect.
For the linkage of a name declared with a static specifier, see [basic.link].
The extern specifier can be applied only to the names of variables and functions.
The extern specifier cannot be used in the declaration of class members or function parameters.
For the linkage of a name declared with an extern specifier, see [basic.link].
[Note
:
The extern keyword can also be used in explicit-instantiations and linkage-specifications, but it is not a storage-class-specifier in such contexts.
end note
]
The linkages implied by successive declarations for a given entity shall agree.
That is, within a given scope, each declaration declaring the same variable name or the same overloading of a function name shall imply the same linkage.
Each function in a given set of overloaded functions can have a different linkage, however.
[Example
:
static char* f();               // f() has internal linkage
char* f()                       // f() still has internal linkage
  { /* ... */ }

char* g();                      // g() has external linkage
static char* g()                // error: inconsistent linkage
  { /* ... */ }

void h();
inline void h();                // external linkage

inline void l();
void l();                       // external linkage

inline void m();
extern void m();                // external linkage

static void n();
inline void n();                // internal linkage

static int a;                   // a has internal linkage
int a;                          // error: two definitions

static int b;                   // b has internal linkage
extern int b;                   // b still has internal linkage

int c;                          // c has external linkage
static int c;                   // error: inconsistent linkage

extern int d;                   // d has external linkage
static int d;                   // error: inconsistent linkage
end example
]
The name of a declared but undefined class can be used in an extern declaration.
Such a declaration can only be used in ways that do not require a complete class type.
[Example
:
struct S;
extern S a;
extern S f();
extern void g(S);

void h() {
  g(a);                         // error: S is incomplete
  f();                          // error: S is incomplete
}
end example
]
The mutable specifier shall appear only in the declaration of a non-static data member whose type is neither const-qualified nor a reference type.
[Example
:
class X {
  mutable const int* p;         // OK
  mutable int* const q;         // ill-formed
};
end example
]
The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const ([dcl.type.cv]).

9.1.2 Function specifiers [dcl.fct.spec]

A function-specifier can be used only in a function declaration.
function-specifier:
	virtual
	explicit-specifier
explicit-specifier:
	explicit ( constant-expression )
	explicit
The virtual specifier shall be used only in the initial declaration of a non-static class member function; see [class.virtual].
An explicit-specifier shall be used only in the declaration of a constructor or conversion function within its class definition; see [class.conv.ctor] and [class.conv.fct].
In an explicit-specifier, the constant-expression, if supplied, shall be a contextually converted constant expression of type bool ([expr.const]).
The explicit-specifier explicit without a constant-expression is equivalent to the explicit-specifier explicit(true).
If the constant expression evaluates to true, the function is explicit.
Otherwise, the function is not explicit.
A ( token that follows explicit is parsed as part of the explicit-specifier.

9.1.3 The typedef specifier [dcl.typedef]

Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental or compound types.
The typedef specifier shall not be combined in a decl-specifier-seq with any other kind of specifier except a defining-type-specifier, and it shall not be used in the decl-specifier-seq of a parameter-declaration nor in the decl-specifier-seq of a function-definition ([dcl.fct.def]).
If a typedef specifier appears in a declaration without a declarator, the program is ill-formed.
typedef-name:
	identifier
A name declared with the typedef specifier becomes a typedef-name.
Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in [dcl.decl].
A typedef-name is thus a synonym for another type.
A typedef-name does not introduce a new type the way a class declaration ([class.name]) or enum declaration does.
[Example
:
After
typedef int MILES, *KLICKSP;
the constructions
MILES distance;
extern KLICKSP metricp;
are all correct declarations; the type of distance is int and that of metricp is “pointer to int.
end example
]
A typedef-name can also be introduced by an alias-declaration.
The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name.
Such a typedef-name has the same semantics as if it were introduced by the typedef specifier.
In particular, it does not define a new type.
[Example
:
using handler_t = void (*)(int);
extern handler_t ignore;
extern void (*ignore)(int);         // redeclare ignore
using cell = pair<void*, cell*>;    // ill-formed
end example
]
The defining-type-specifier-seq of the defining-type-id shall not define a class or enumeration if the alias-declaration is the declaration of a template-declaration.
In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.
[Example
:
typedef struct s { /* ... */ } s;
typedef int I;
typedef int I;
typedef I I;
end example
]
In a given class scope, a typedef specifier can be used to redefine any class-name declared in that scope that is not also a typedef-name to refer to the type to which it already refers.
[Example
:
struct S {
  typedef struct A { } A;       // OK
  typedef struct B B;           // OK
  typedef A A;                  // error
};
end example
]
If a typedef specifier is used to redefine in a given scope an entity that can be referenced using an elaborated-type-specifier, the entity can continue to be referenced by an elaborated-type-specifier or as an enumeration or class name in an enumeration or class definition respectively.
[Example
:
struct S;
typedef struct S S;
int main() {
  struct S* p;                  // OK
}
struct S { };                   // OK
end example
]
In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type.
[Example
:
class complex { /* ... */ };
typedef int complex;            // error: redefinition
end example
]
Similarly, in a given scope, a class or enumeration shall not be declared with the same name as a typedef-name that is declared in that scope and refers to a type other than the class or enumeration itself.
[Example
:
typedef int complex;
class complex { /* ... */ };    // error: redefinition
end example
]
[Note
:
A typedef-name that names a class type, or a cv-qualified version thereof, is also a class-name ([class.name]).
If a typedef-name is used to identify the subject of an elaborated-type-specifier, a class definition, a constructor declaration, or a destructor declaration, the program is ill-formed.
end note
]
[Example
:
struct S {
  S();
  ~S();
};

typedef struct S T;

S a = T();                      // OK
struct T * p;                   // error
end example
]
If the typedef declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration to be that class type (or enum type) is used to denote the class type (or enum type) for linkage purposes only ([basic.link]).
[Note
:
A typedef declaration involving a lambda-expression does not itself define the associated closure type, and so the closure type is not given a name for linkage purposes.
end note
]
[Example
:
typedef struct { } *ps, S;      // S is the class name for linkage purposes
typedef decltype([]{}) C;       // the closure type has no name for linkage purposes
end example
]

9.1.4 The friend specifier [dcl.friend]

The friend specifier is used to specify access to class members; see [class.friend].

9.1.5 The constexpr specifier [dcl.constexpr]

The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template.
A function or static data member declared with the constexpr specifier is implicitly an inline function or variable ([dcl.inline]).
If any declaration of a function or function template has a constexpr specifier, then all its declarations shall contain the constexpr specifier.
[Note
:
An explicit specialization can differ from the template declaration with respect to the constexpr specifier.
end note
]
[Note
:
Function parameters cannot be declared constexpr.
end note
]
[Example
:
constexpr void square(int &x);  // OK: declaration
constexpr int bufsz = 1024;     // OK: definition
constexpr struct pixel {        // error: pixel is a type
  int x;
  int y;
  constexpr pixel(int);         // OK: declaration
};
constexpr pixel::pixel(int a)
  : x(a), y(x)                  // OK: definition
  { square(x); }
constexpr pixel small(2);       // error: square not defined, so small(2)
                                // not constant ([expr.const]) so constexpr not satisfied

constexpr void square(int &x) { // OK: definition
  x *= x;
}
constexpr pixel large(4);       // OK: square defined
int next(constexpr int x) {     // error: not for parameters
     return x + 1;
}
extern constexpr int memsz;     // error: not a definition
end example
]
A constexpr specifier used in the declaration of a function that is not a constructor declares that function to be a constexpr function.
Similarly, a constexpr specifier used in a constructor declaration declares that constructor to be a constexpr constructor.
The definition of a constexpr function shall satisfy the following requirements:
[Example
:
constexpr int square(int x)
  { return x * x; }             // OK
constexpr long long_max()
  { return 2147483647; }        // OK
constexpr int abs(int x) {
  if (x < 0)
    x = -x;
  return x;                     // OK
}
constexpr int first(int n) {
  static int value = n;         // error: variable has static storage duration
  return value;
}
constexpr int uninit() {
  int a;                        // error: variable is uninitialized
  return a;
}
constexpr int prev(int x)
  { return --x; }               // OK
constexpr int g(int x, int n) { // OK
  int r = 1;
  while (--n > 0) r *= x;
  return r;
}
end example
]
The definition of a constexpr constructor shall satisfy the following requirements:
In addition, either its function-body shall be = delete, or it shall satisfy the following requirements:
  • either its function-body shall be = default, or the compound-statement of its function-body shall satisfy the requirements for a function-body of a constexpr function;
  • every non-variant non-static data member and base class subobject shall be initialized ([class.base.init]);
  • if the class is a union having variant members ([class.union]), exactly one of them shall be initialized;
  • if the class is a union-like class, but is not a union, for each of its anonymous union members having variant members, exactly one of them shall be initialized;
  • for a non-delegating constructor, every constructor selected to initialize non-static data members and base class subobjects shall be a constexpr constructor;
  • for a delegating constructor, the target constructor shall be a constexpr constructor.
[Example
:
struct Length {
  constexpr explicit Length(int i = 0) : val(i) { }
private:
  int val;
};
end example
]
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, a constant initializer for some object ([basic.start.static]), the program is ill-formed, no diagnostic required.
[Example
:
constexpr int f(bool b)
  { return b ? throw 0 : 0; }           // OK
constexpr int f() { return f(true); }   // ill-formed, no diagnostic required

struct B {
  constexpr B(int x) : i(0) { }         // x is unused
  int i;
};

int global;

struct D : B {
  constexpr D() : B(global) { }         // ill-formed, no diagnostic required
                                        // lvalue-to-rvalue conversion on non-constant global
};
end example
]
If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression.
If no specialization of the template would satisfy the requirements for a constexpr function or constexpr constructor when considered as a non-template function or constructor, the template is ill-formed, no diagnostic required.
A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function in all respects except that
The constexpr specifier has no effect on the type of a constexpr function or a constexpr constructor.
[Example
:
constexpr int bar(int x, int y)         // OK
    { return x + y + x*y; }
// ...
int bar(int x, int y)                   // error: redefinition of bar
    { return x * 2 + 3 * y; }
end example
]
A constexpr specifier used in an object declaration declares the object as const.
Such an object shall have literal type and shall be initialized.
In any constexpr variable declaration, the full-expression of the initialization shall be a constant expression.
[Example
:
struct pixel {
  int x, y;
};
constexpr pixel ur = { 1294, 1024 };    // OK
constexpr pixel origin;                 // error: initializer missing
end example
]

9.1.6 The inline specifier [dcl.inline]

The inline specifier can be applied only to the declaration or definition of a variable or function.
A function declaration ([dcl.fct], [class.mfct], [class.friend]) with an inline specifier declares an inline function.
The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism.
An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions specified in this subclause shall still be respected.
A variable declaration with an inline specifier declares an inline variable.
A function defined within a class definition is an inline function.
The inline specifier shall not appear on a block scope declaration.94
If the inline specifier is used in a friend function declaration, that declaration shall be a definition or the function shall have previously been declared inline.
An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case ([basic.def.odr]).
[Note
:
A call to the inline function or a use of the inline variable may be encountered before its definition appears in the translation unit.
end note
]
If the definition of a function or variable appears in a translation unit before its first declaration as inline, the program is ill-formed.
If a function or variable with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required.
An inline function or variable with external linkage shall have the same address in all translation units.
[Note
:
A static local variable in an inline function with external linkage always refers to the same object.
A type defined within the body of an inline function with external linkage is the same type in every translation unit.
end note
]
The inline keyword has no effect on the linkage of a function.

9.1.7 Type specifiers [dcl.type]

As a general rule, at most one defining-type-specifier is allowed in the complete decl-specifier-seq of a declaration or in a defining-type-specifier-seq, and at most one type-specifier is allowed in a type-specifier-seq.
The only exceptions to this rule are the following:
  • const can be combined with any type specifier except itself.
  • volatile can be combined with any type specifier except itself.
  • signed or unsigned can be combined with char, long, short, or int.
  • short or long can be combined with int.
  • long can be combined with double.
  • long can be combined with long.
Except in a declaration of a constructor, destructor, or conversion function, at least one defining-type-specifier that is not a cv-qualifier shall appear in a complete type-specifier-seq or a complete decl-specifier-seq.95
[Note
:
enum-specifiers, class-specifiers, and typename-specifiers are discussed in [dcl.enum], [class], and [temp.res], respectively.
The remaining type-specifiers are discussed in the rest of this subclause.
end note
]
There is no special provision for a decl-specifier-seq that lacks a type-specifier or that has a type-specifier that only specifies cv-qualifiers.
The “implicit int” rule of C is no longer supported.

9.1.7.1 The cv-qualifiers [dcl.type.cv]

There are two cv-qualifiers, const and volatile.
Each cv-qualifier shall appear at most once in a cv-qualifier-seq.
If a cv-qualifier appears in a decl-specifier-seq, the init-declarator-list or member-declarator-list of the declaration shall not be empty.
[Note
:
[basic.type.qualifier] and [dcl.fct] describe how cv-qualifiers affect object and function types.
end note
]
Redundant cv-qualifications are ignored.
[Note
:
For example, these could be introduced by typedefs.
end note
]
[Note
:
Declaring a variable const can affect its linkage ([dcl.stc]) and its usability in constant expressions.
As described in [dcl.init], the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization.
end note
]
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path.
[Note
:
Cv-qualifiers are supported by the type system so that they cannot be subverted without casting.
end note
]
Except that any class member declared mutable ([dcl.stc]) can be modified, any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object ([basic.type.qualifier]) during its lifetime ([basic.life]) results in undefined behavior.
[Example
:
const int ci = 3;                       // cv-qualified (initialized as required)
ci = 4;                                 // ill-formed: attempt to modify const

int i = 2;                              // not cv-qualified
const int* cip;                         // pointer to const int
cip = &i;                               // OK: cv-qualified access path to unqualified
*cip = 4;                               // ill-formed: attempt to modify through ptr to const

int* ip;
ip = const_cast<int*>(cip);             // cast needed to convert const int* to int*
*ip = 4;                                // defined: *ip points to i, a non-const object

const int* ciq = new const int (3);     // initialized as required
int* iq = const_cast<int*>(ciq);        // cast required
*iq = 4;                                // undefined: modifies a const object
For another example,
struct X {
  mutable int i;
  int j;
};
struct Y {
  X x;
  Y();
};

const Y y;
y.x.i++;                                // well-formed: mutable member can be modified
y.x.j++;                                // ill-formed: const-qualified member modified
Y* p = const_cast<Y*>(&y);              // cast away const-ness of y
p->x.i = 99;                            // well-formed: mutable member can be modified
p->x.j = 99;                            // undefined: modifies a const subobject
end example
]
The semantics of an access through a volatile glvalue are implementation-defined.
If an attempt is made to access an object defined with a volatile-qualified type through the use of a non-volatile glvalue, the behavior is undefined.
[Note
:
volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation.
Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object.
See [intro.execution] for detailed semantics.
In general, the semantics of volatile are intended to be the same in C++ as they are in C.
end note
]

9.1.7.2 Simple type specifiers [dcl.type.simple]

The simple type specifiers are
simple-type-specifier:
	nested-name-specifier type-name
	nested-name-specifier template simple-template-id
	nested-name-specifier template-name
	char
	char16_t
	char32_t
	wchar_t
	bool
	short
	int
	long
	signed
	unsigned
	float
	double
	void
	auto
	decltype-specifier
type-name:
	class-name
	enum-name
	typedef-name
	simple-template-id
decltype-specifier:
	decltype ( expression )
	decltype ( auto )
The simple-type-specifier auto is a placeholder for a type to be deduced ([dcl.spec.auto]).
A type-specifier of the form typename nested-name-specifier template-name is a placeholder for a deduced class type ([dcl.type.class.deduct]).
The template-name shall name a class template that is not an injected-class-name.
The other simple-type-specifiers specify either a previously-declared type, a type determined from an expression, or one of the fundamental types ([basic.fundamental]).
Table 11 summarizes the valid combinations of simple-type-specifiers and the types they specify.
Table 11simple-type-specifiers and the types they specify
Specifier(s)
Type
type-name
the type named
simple-template-id
the type as defined in [temp.names]
template-name
placeholder for a type to be deduced
char
char
unsigned char
unsigned char
signed char
signed char
char16_­t
char16_­t
char32_­t
char32_­t
bool
bool
unsigned
unsigned int
unsigned int
unsigned int
signed
int
signed int
int
int
int
unsigned short int
unsigned short int
unsigned short
unsigned short int
unsigned long int
unsigned long int
unsigned long
unsigned long int
unsigned long long int
unsigned long long int
unsigned long long
unsigned long long int
signed long int
long int
signed long
long int
signed long long int
long long int
signed long long
long long int
long long int
long long int
long long
long long int
long int
long int
long
long int
signed short int
short int
signed short
short int
short int
short int
short
short int
wchar_­t
wchar_­t
float
float
double
double
long double
long double
void
void
auto
placeholder for a type to be deduced
decltype(auto)
placeholder for a type to be deduced
decltype(expression)
the type as defined below
When multiple simple-type-specifiers are allowed, they can be freely intermixed with other decl-specifiers in any order.
[Note
:
It is implementation-defined whether objects of char type are represented as signed or unsigned quantities.
The signed specifier forces char objects to be signed; it is redundant in other contexts.
end note
]
For an expression e, the type denoted by decltype(e) is defined as follows:
The operand of the decltype specifier is an unevaluated operand.
[Example
:
const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 17;        // type is const int&&
decltype(i) x2;                 // type is int
decltype(a->x) x3;              // type is double
decltype((a->x)) x4 = x3;       // type is const double&
end example
]
[Note
:
The rules for determining types involving decltype(auto) are specified in [dcl.spec.auto].
end note
]
If the operand of a decltype-specifier is a prvalue, the temporary materialization conversion is not applied and no result object is provided for the prvalue.
The type of the prvalue may be incomplete or an abstract class type.
[Note
:
As a result, storage is not allocated for the prvalue and it is not destroyed.
Thus, a class type is not instantiated as a result of being the type of a function call in this context.
In this context, the common purpose of writing the expression is merely to refer to its type.
In that sense, a decltype-specifier is analogous to a use of a typedef-name, so the usual reasons for requiring a complete type do not apply.
In particular, it is not necessary to allocate storage for a temporary object or to enforce the semantic constraints associated with invoking the type's destructor.
end note
]
[Note
:
Unlike the preceding rule, parentheses have no special meaning in this context.
end note
]
[Example
:
template<class T> struct A { ~A() = delete; };
template<class T> auto h()
  -> A<T>;
template<class T> auto i(T)     // identity
  -> T;
template<class T> auto f(T)     // #1
  -> decltype(i(h<T>()));       // forces completion of A<T> and implicitly uses A<T>​::​~A()
                                // for the temporary introduced by the use of h().
                                // (A temporary is not introduced as a result of the use of i().)
template<class T> auto f(T)     // #2
  -> void;
auto g() -> void {
  f(42);                        // OK: calls #2. (#1 is not a viable candidate: type deduction
                                // fails ([temp.deduct]) because A<int>​::​~A() is implicitly used in its
                                // decltype-specifier)
}
template<class T> auto q(T)
  -> decltype((h<T>()));        // does not force completion of A<T>; A<T>​::​~A() is not implicitly
                                // used within the context of this decltype-specifier
void r() {
  q(42);                        // error: deduction against q succeeds, so overload resolution selects
                                // the specialization “q(T) -> decltype((h<T>()))” with Tint;
                                // the return type is A<int>, so a temporary is introduced and its
                                // destructor is used, so the program is ill-formed
}
end example
]

9.1.7.3 Elaborated type specifiers [dcl.type.elab]

elaborated-type-specifier:
	class-key attribute-specifier-seq nested-name-specifier identifier
	class-key simple-template-id
	class-key nested-name-specifier template simple-template-id
	enum nested-name-specifier identifier
An attribute-specifier-seq shall not appear in an elaborated-type-specifier unless the latter is the sole constituent of a declaration.
If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization, an explicit instantiation or it has one of the following forms:
class-key attribute-specifier-seq identifier ;
friend class-key :: identifier ;
friend class-key :: simple-template-id ;
friend class-key nested-name-specifier identifier ;
friend class-key nested-name-specifier template simple-template-id ;
In the first case, the attribute-specifier-seq, if any, appertains to the class being declared; the attributes in the attribute-specifier-seq are thereafter considered attributes of the class whenever it is named.
[basic.lookup.elab] describes how name lookup proceeds for the identifier in an elaborated-type-specifier.
If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name.
If the identifier resolves to a typedef-name or the simple-template-id resolves to an alias template specialization, the elaborated-type-specifier is ill-formed.
[Note
:
This implies that, within a class template with a template type-parameter T, the declaration
friend class T;
is ill-formed.
However, the similar declaration friend T; is allowed ([class.friend]).
end note
]
The class-key or enum keyword present in the elaborated-type-specifier shall agree in kind with the declaration to which the name in the elaborated-type-specifier refers.
This rule also applies to the form of elaborated-type-specifier that declares a class-name or friend class since it can be construed as referring to the definition of the class.
Thus, in any elaborated-type-specifier, the enum keyword shall be used to refer to an enumeration, the union class-key shall be used to refer to a union, and either the class or struct class-key shall be used to refer to a class declared using the class or struct class-key.
[Example
:
enum class E { a, b };
enum E x = E::a;                // OK
end example
]

9.1.7.4 The auto specifier [dcl.spec.auto]

The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer.
The auto type-specifier is also used to introduce a function type having a trailing-return-type or to signify that a lambda is a generic lambda ([expr.prim.lambda]).
The auto type-specifier is also used to introduce a structured binding declaration.
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid.
If the function declarator includes a trailing-return-type ([dcl.fct]), that trailing-return-type specifies the declared return type of the function.
Otherwise, the function declarator shall declare a function.
If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded return statements, if any, in the body of the function ([stmt.if]).
The type of a variable declared using auto or decltype(auto) is deduced from its initializer.
This use is allowed in an initializing declaration ([dcl.init]) of a variable.
auto or decltype(auto) shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-specifier-seq shall be followed by one or more declarators, each of which shall be followed by a non-empty initializer.
In an initializer of the form
( expression-list )
the expression-list shall be a single assignment-expression.
[Example
:
auto x = 5;                     // OK: x has type int
const auto *v = &x, u = 6;      // OK: v has type const int*, u has type const int
static auto y = 0.0;            // OK: y has type double
auto int r;                     // error: auto is not a storage-class-specifier
auto f() -> int;                // OK: f returns int
auto g() { return 0.0; }        // OK: g returns double
auto h();                       // OK: h's return type will be deduced when it is defined
end example
]
A placeholder type can also be used in the type-specifier-seq in the new-type-id or type-id of a new-expression and as a decl-specifier of the parameter-declaration's decl-specifier-seq in a template-parameter.
A program that uses auto or decltype(auto) in a context not explicitly allowed in this subclause is ill-formed.
If the init-declarator-list contains more than one init-declarator, they shall all form declarations of variables.
The type of each declared variable is determined by placeholder type deduction, and if the type that replaces the placeholder type is not the same in each deduction, the program is ill-formed.
[Example
:
auto x = 5, *y = &x;            // OK: auto is int
auto a = 5, b = { 1, 2 };       // error: different types for auto
end example
]
If a function with a declared return type that contains a placeholder type has multiple non-discarded return statements, the return type is deduced for each such return statement.
If the type deduced is not the same in each deduction, the program is ill-formed.
If a function with a declared return type that uses a placeholder type has no non-discarded return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body.
[Example
:
auto  f() { }                   // OK, return type is void
auto* g() { }                   // error, cannot deduce auto* from void()
end example
]
If the name of an entity with an undeduced placeholder type appears in an expression, the program is ill-formed.
Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.
[Example
:
auto n = n;                     // error, n's initializer refers to n
auto f();
void g() { &f; }                // error, f's return type is unknown
auto sum(int i) {
  if (i == 1)
    return i;                   // sum's return type is int
  else
    return sum(i-1)+i;          // OK, sum's return type has been deduced
}
end example
]
Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand.
[Note
:
Therefore, any use of a specialization of the function template will cause an implicit instantiation.
Any errors that arise from this instantiation are not in the immediate context of the function type and can result in the program being ill-formed ([temp.deduct]).
end note
]
[Example
:
template <class T> auto f(T t) { return t; }    // return type deduced at instantiation time
typedef decltype(f(1)) fint_t;                  // instantiates f<int> to deduce return type
template<class T> auto f(T* t) { return *t; }
void g() { int (*p)(int*) = &f; }               // instantiates both fs to determine return types,
                                                // chooses second
end example
]
Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type.
Similarly, redeclarations or specializations of a function or function template with a declared return type that does not use a placeholder type shall not use a placeholder.
[Example
:
auto f();
auto f() { return 42; }                         // return type is int
auto f();                                       // OK
int f();                                        // error, cannot be overloaded with auto f()
decltype(auto) f();                             // error, auto and decltype(auto) don't match

template <typename T> auto g(T t) { return t; } // #1
template auto g(int);                           // OK, return type is int
template char g(char);                          // error, no matching template
template<> auto g(double);                      // OK, forward declaration with unknown return type

template <class T> T g(T t) { return t; }       // OK, not functionally equivalent to #1
template char g(char);                          // OK, now there is a matching template
template auto g(float);                         // still matches #1

void h() { return g(42); }                      // error, ambiguous

template <typename T> struct A {
  friend T frf(T);
};
auto frf(int i) { return i; }                   // not a friend of A<int>
end example
]
A function declared with a return type that uses a placeholder type shall not be virtual.
An explicit instantiation declaration does not cause the instantiation of an entity declared using a placeholder type, but it also does not prevent that entity from being instantiated as needed to determine its type.
[Example
:
template <typename T> auto f(T t) { return t; }
extern template auto f(int);    // does not instantiate f<int>
int (*p)(int) = f;              // instantiates f<int> to determine its return type, but an explicit
                                // instantiation definition is still required somewhere in the program
end example
]

9.1.7.4.1 Placeholder type deduction [dcl.type.auto.deduct]

Placeholder type deduction is the process by which a type containing a placeholder type is replaced by a deduced type.
A type T containing a placeholder type, and a corresponding initializer e, are determined as follows:
  • for a non-discarded return statement that occurs in a function declared with a return type that contains a placeholder type, T is the declared return type and e is the operand of the return statement.
    If the return statement has no operand, then e is void();
  • for a variable declared with a type that contains a placeholder type, T is the declared type of the variable and e is the initializer.
    If the initialization is direct-list-initialization, the initializer shall be a braced-init-list containing only a single assignment-expression and e is the assignment-expression;
  • for a non-type template parameter declared with a type that contains a placeholder type, T is the declared type of the non-type template parameter and e is the corresponding template argument.
In the case of a return statement with no operand or with an operand of type void, T shall be either decltype(auto) or cv auto.
If the deduction is for a return statement and e is a braced-init-list ([dcl.init.list]), the program is ill-formed.
If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction.
Obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initialization is copy-list-initialization, with std::initializer_­list<U>.
Deduce a value for U using the rules of template argument deduction from a function call, where P is a function template parameter type and the corresponding argument is e.
If the deduction fails, the declaration is ill-formed.
Otherwise, T' is obtained by substituting the deduced U into P.
[Example
:
auto x1 = { 1, 2 };             // decltype(x1) is std​::​initializer_­list<int>
auto x2 = { 1, 2.0 };           // error: cannot deduce element type
auto x3{ 1, 2 };                // error: not a single element
auto x4 = { 3 };                // decltype(x4) is std​::​initializer_­list<int>
auto x5{ 3 };                   // decltype(x5) is int
end example
]
[Example
:
const auto &i = expr;
The type of i is the deduced type of the parameter u in the call f(expr) of the following invented function template:
template <class U> void f(const U& u);
end example
]
If the placeholder is the decltype(auto) type-specifier, T shall be the placeholder alone.
The type deduced for T is determined as described in [dcl.type.simple], as though e had been the operand of the decltype.
[Example
:
int i;
int&& f();
auto           x2a(i);          // decltype(x2a) is int
decltype(auto) x2d(i);          // decltype(x2d) is int
auto           x3a = i;         // decltype(x3a) is int
decltype(auto) x3d = i;         // decltype(x3d) is int
auto           x4a = (i);       // decltype(x4a) is int
decltype(auto) x4d = (i);       // decltype(x4d) is int&
auto           x5a = f();       // decltype(x5a) is int
decltype(auto) x5d = f();       // decltype(x5d) is int&&
auto           x6a = { 1, 2 };  // decltype(x6a) is std​::​initializer_­list<int>
decltype(auto) x6d = { 1, 2 };  // error, { 1, 2 } is not an expression
auto          *x7a = &i;        // decltype(x7a) is int*
decltype(auto)*x7d = &i;        // error, declared type is not plain decltype(auto)
end example
]

9.1.7.5 Deduced class template specialization types [dcl.type.class.deduct]

If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of an initializing declaration ([dcl.init]) of a variable, the placeholder is replaced by the return type of the function selected by overload resolution for class template deduction ([over.match.class.deduct]).
If the decl-specifier-seq is followed by an init-declarator-list or member-declarator-list containing more than one declarator, the type that replaces the placeholder shall be the same in each deduction.
A placeholder for a deduced class type can also be used in the type-specifier-seq in the new-type-id or type-id of a new-expression, as the simple-type-specifier in an explicit type conversion (functional notation), or as the type-specifier in the parameter-declaration of a template-parameter.
A placeholder for a deduced class type shall not appear in any other context.
[Example
:
template<class T> struct container {
    container(T t) {}
    template<class Iter> container(Iter beg, Iter end);
};
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
std::vector<double> v = { /* ... */ };

container c(7);                         // OK, deduces int for T
auto d = container(v.begin(), v.end()); // OK, deduces double for T
container e{5, 6};                      // error, int is not an iterator
end example
]

9.2 Declarators [dcl.decl]

A declarator declares a single variable, 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 initializer
	declarator requires-clause
The three components of a simple-declaration are the attributes ([dcl.attr]), the specifiers (decl-specifier-seq; [dcl.spec]) and the declarators (init-declarator-list).
The specifiers indicate the type, storage class or other properties of the entities being declared.
The declarators specify the names of these entities and (optionally) 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].
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.
[Note
:
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 equivalent to
T D1; T D2; ... T Dn;
where T is a decl-specifier-seq and each Di is an init-declarator.
One exception is when a name introduced by one of the declarators hides a type name used by the decl-specifiers, so that when the same decl-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
Another exception is when T is auto ([dcl.spec.auto]), for example:
auto i = 1, j = 2.0;    // error: deduced types for i and j do not match
as opposed to
auto i = 1;             // OK: i deduced to have type int
auto j = 2.0;           // OK: j deduced to have type double
end note
]
The optional requires-clause in an init-declarator or member-declarator shall not be present when the declarator does not declare a function ([dcl.fct]).
When present after a declarator, the requires-clause is called the trailing requires-clause.
The trailing requires-clause introduces the constraint-expression that results from interpreting its constraint-logical-or-expression as a constraint-expression.
[Example
:
void f1(int a) requires true;               // OK
auto f2(int a) -> bool requires true;       // OK
auto f3(int a) requires true -> bool;       // error: requires-clause precedes trailing-return-type
void (*pf)() requires true;                 // error: constraint on a variable
void g(int (*)() requires true);            // error: constraint on a parameter-declaration

auto* p = new void(*)(char) requires true;  // error: not a function declaration
end example
]

9.2.1 Type names [dcl.name]

To specify type conversions explicitly, and as an argument of sizeof, alignof, 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 a variable or function of that type that omits the name of the entity.
type-id:
	type-specifier-seq abstract-declarator
defining-type-id:
	defining-type-specifier-seq abstract-declarator
abstract-declarator:
	ptr-abstract-declarator
	noptr-abstract-declarator parameters-and-qualifiers trailing-return-type
	abstract-pack-declarator
ptr-abstract-declarator:
	noptr-abstract-declarator
	ptr-operator ptr-abstract-declarator
noptr-abstract-declarator:
	noptr-abstract-declarator parameters-and-qualifiers
	noptr-abstract-declarator [ constant-expression ] attribute-specifier-seq
	( ptr-abstract-declarator )
abstract-pack-declarator:
	noptr-abstract-pack-declarator
	ptr-operator abstract-pack-declarator
noptr-abstract-pack-declarator:
	noptr-abstract-pack-declarator parameters-and-qualifiers
	noptr-abstract-pack-declarator [ constant-expression ] attribute-specifier-seq
	...
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 parameters) returning pointer to int”, and “pointer to a function of (double) returning int.
end example
]
A type can also be named (often more easily) by using a typedef ([dcl.typedef]).

9.2.2 Ambiguity resolution [dcl.ambig.res]

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 adding parentheses around the argument.
The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast.
end note
]
[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 y((int)a);                  // object declaration
  S z = int(a);                 // object declaration
}
end example
]
An ambiguity can arise from the similarity between a function-style cast and a type-id.
The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
[Example
:
template <class T> struct X {};
template <int N> struct Y {};
X<int()> a;                     // type-id
X<int(1)> b;                    // expression (ill-formed)
Y<int()> c;                     // type-id (ill-formed)
Y<int(1)> d;                    // expression

void foo(signed char a) {
  sizeof(int());                // type-id (ill-formed)
  sizeof(int(a));               // expression
  sizeof(int(unsigned(a)));     // type-id (ill-formed)

  (int())+1;                    // type-id (ill-formed)
  (int(a))+1;                   // expression
  (int(unsigned(a)))+1;         // type-id (ill-formed)
}
end example
]
Another ambiguity arises in a parameter-declaration-clause 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 pointer
  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
]

9.2.3 Meaning of declarators [dcl.meaning]

A declarator contains exactly one declarator-id; it names the identifier that is declared.
An unqualified-id occurring in a declarator-id shall be a simple identifier except for the declaration of some special functions ([class.ctor], [class.conv], [class.dtor], [over.oper]) and for the declaration of template specializations or partial specializations ([temp.spec]).
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace ([namespace.def])) or to a specialization thereof; the member shall not merely 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.
The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier.
[Note
:
If the qualifier is the global :: scope resolution operator, the declarator-id refers to a name declared in the global namespace scope.
end note
]
The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared.
A static, thread_­local, extern, mutable, friend, inline, virtual, constexpr, or typedef specifier or an explicit-specifier applies directly to each declarator-id in an init-declarator-list or member-declarator-list; the type specified for each declarator-id depends on both the decl-specifier-seq and its declarator.
Thus, a declaration of a particular identifier has the form
T D
where T is of the form attribute-specifier-seq decl-specifier-seq and D is a declarator.
Following is a recursive procedure for determining the type specified for the contained declarator-id by such a declaration.
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]).
end example
]
In a declaration attribute-specifier-seq T D where D is an unadorned identifier the type of this identifier is “T.
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.

9.2.3.1 Pointers [dcl.ptr]

In a declaration T D where D has the form
* attribute-specifier-seq cv-qualifier-seq 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.
Similarly, the optional attribute-specifier-seq appertains to the pointer and not to the object pointed to.
[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-unqualified pointer later, for example:
*ppc = &ci;         // OK, but would make p point to ci because of previous error
*p = 5;             // clobber ci
end example
]
[Note
:
Forming a pointer to reference type is ill-formed; see [dcl.ref].
Forming a function pointer type is ill-formed if the function type has cv-qualifiers or a ref-qualifier; see [dcl.fct].
Since the address of a bit-field ([class.bit]) cannot be taken, a pointer can never point to a bit-field.
end note
]

9.2.3.2 References [dcl.ref]

In a declaration T D where D has either of the forms
& attribute-specifier-seq D1
&& attribute-specifier-seq 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.
The optional attribute-specifier-seq appertains to the reference type.
Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name ([dcl.typedef], [temp.param]) or decltype-specifier, in which case the cv-qualifiers are ignored.
[Example
:
typedef int& A;
const A aref = 3;   // ill-formed; lvalue reference to non-const initialized with rvalue
The type of aref is “lvalue reference to int”, not “lvalue reference to const int.
end example
]
[Note
:
A reference can be thought of as a name of an object.
end note
]
A declarator that specifies the type “reference to cv void” is ill-formed.
A reference type that is declared using & is called an lvalue reference, and a reference type that is declared using && is called an rvalue reference.
Lvalue references and rvalue references are distinct types.
Except where explicitly noted, they are semantically equivalent and commonly referred to as references.
[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.
end example
]
It is unspecified whether or not a reference requires storage ([basic.stc]).
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 definition, or is the declaration of a parameter or a return type ([dcl.fct]); see [basic.def].
A reference shall be initialized to refer to a valid object or function.
[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 indirection through a null pointer, which causes undefined behavior.
As described in [class.bit], a reference cannot be bound directly to a bit-field.
end note
]
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.
[Note
:
This rule is known as reference collapsing.
end note
]
[Example
:
int i;
typedef int& LRI;
typedef int&& RRI;

LRI& r1 = i;                    // r1 has the type int&
const LRI& r2 = i;              // r2 has the type int&
const LRI&& r3 = i;             // r3 has the type int&

RRI& r4 = i;                    // r4 has the type int&
RRI&& r5 = 5;                   // r5 has the type int&&

decltype(r2)& r6 = i;           // r6 has the type int&
decltype(r2)&& r7 = i;          // r7 has the type int&
end example
]
[Note
:
Forming a reference to function type is ill-formed if the function type has cv-qualifiers or a ref-qualifier; see [dcl.fct].
end note
]

9.2.3.3 Pointers to members [dcl.mptr]

In a declaration T D where D has the form
nested-name-specifier * attribute-specifier-seq cv-qualifier-seq D1
and the nested-name-specifier denotes a class, 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 member of class nested-name-specifier of type T.
The optional attribute-specifier-seq appertains to the pointer-to-member.
[Example
:
struct X {
  void f(int);
  int a;
};
struct 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
]
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
:
The type “pointer to member” 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++.
end note
]

9.2.3.4 Arrays [dcl.array]

In a declaration T D where D has the form
D1 [ constant-expression ] attribute-specifier-seq
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; if the type of the identifier of D contains the auto type-specifier, the program is ill-formed.
T is called the array element type; this type shall not be a reference type, cv void, or a function type.
If the constant-expression is present, it shall be a converted constant expression of type std::size_­t 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 subobjects of type T.
Except as noted below, 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.
The optional attribute-specifier-seq appertains to the array.
[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-qualified type; see [basic.type.qualifier].
end note
]
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.
When several “array of” specifications are adjacent, a multidimensional array type is created; only the first of the constant expressions that specify the bounds of the arrays may be omitted.
In addition to declarations in which an incomplete object type is allowed, an array bound may be omitted in some cases in the declaration of a function parameter ([dcl.fct]).
An array bound may also be omitted when the declarator is followed by an initializer, when a declarator for a static data member is followed by a brace-or-equal-initializer ([class.mem]), or in an explicit type conversion ([expr.type.conv]).
In these cases, 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.
Furthermore, if there is a preceding declaration of the entity in the same scope in which the bound was specified, an omitted array bound is taken to be the same as in that earlier declaration, and similarly for the definition of a static data member of a class.
[Example
:
float fa[17], *afp[17];
declares an array of float numbers and an array of pointers to float numbers.
end example
]
[Example
:
int x3d[3][5][7];
declares an array of three elements, each of which is an array of five elements, each of which is an array of seven integers.
The overall array can be viewed as a three-dimensional array of integers, with rank .
Any of the expressions x3d, x3d[i], x3d[i][j], x3d[i][j][k] can reasonably appear in an expression.
The expression x3d[i] is equivalent to *(x3d + i); in that expression, x3d is subject to the array-to-pointer conversion ([conv.array]) and is first converted to a pointer to a 2-dimensional array with rank that points to the first element of x3d.
Then i is added, which on typical implementations involves multiplying i by the length of the object to which the pointer points, which is sizeof(int).
The result of the addition and indirection is an lvalue denoting the i array element of x3d (an array of five arrays of seven integers).
If there is another subscript, the same argument applies again, so x3d[i][j] is an lvalue denoting the j array element of the i array element of x3d (an array of seven integers), and x3d[i][j][k] is an lvalue denoting the k array element of the j array element of the i array element of x3d (an integer).
end example
]
[Note
:
The first subscript in the declaration helps determine the amount of storage consumed by an array but plays no other part in subscript calculations.
end note
]
[Example
:
extern int x[10];
struct S {
  static int y[10];
};

int x[];                // OK: bound is 10
int S::y[];             // OK: bound is 10

void f() {
  extern int x[];
  int i = sizeof(x);    // error: incomplete object type
}
end example
]
[Note
:
Conversions affecting expressions of array type are described in [conv.array].
end note
]
[Note
:
The subscript operator can be overloaded for a class ([over.sub]).
For the operator's built-in meaning, see [expr.sub].
end note
]

9.2.3.5 Functions [dcl.fct]

In a declaration T D where D has the form
D1 ( parameter-declaration-clause ) cv-qualifier-seq
	ref-qualifier noexcept-specifier attribute-specifier-seq
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 noexcept function of (parameter-declaration-clause) cv-qualifier-seq ref-qualifier returning T”, where the optional noexcept is present if and only if the exception specification ([except.spec]) is non-throwing.
The optional attribute-specifier-seq appertains to the function type.
In a declaration T D where D has the form
D1 ( parameter-declaration-clause ) cv-qualifier-seq
	ref-qualifier noexcept-specifier attribute-specifier-seq trailing-return-type
and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, T shall be the single type-specifier auto.
The type of the declarator-id in D is “derived-declarator-type-list noexcept function of (parameter-declaration-clause) cv-qualifier-seq ref-qualifier returning U”, where U is the type specified by the trailing-return-type, and where the optional noexcept is present if and only if the exception specification is non-throwing.
The optional attribute-specifier-seq appertains to the function type.
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].
end note
]
If the parameter-declaration-clause is empty, the function takes no arguments.
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
Except for this special case, a parameter shall not have type cv void.
If the parameter-declaration-clause terminates with an ellipsis or a function parameter pack ([temp.variadic]), the number of arguments shall be equal to or greater than the number of parameters that do not have a default argument and are not function parameter packs.
Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” 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*
end example
]
[Note
:
The standard header <cstdarg> contains a mechanism for accessing arguments passed using the ellipsis (see [expr.call] and [support.runtime]).
end note
]
The type of a function is determined using the following rules.
The type of each parameter (including function parameter packs) 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 of function type T is adjusted to be “pointer to T.
After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.
The resulting list of transformed parameter types and the presence or absence of the ellipsis or a function parameter pack is the function's parameter-type-list.
[Note
:
This transformation does not affect the types of the parameters.
For example, int(*)(const int p, decltype(p)*) and int(*)(int, const int*) are identical types.
end note
]
A function type with a cv-qualifier-seq or a ref-qualifier (including a type named by typedef-name ([dcl.typedef], [temp.param])) shall appear only as:
[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
]
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.
In the latter case, the cv-qualifiers are ignored.
[Note
:
A function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types.
end note
]
[Example
:
typedef void F();
struct S {
  const F f;        // OK: equivalent to: void f();
};
end example
]
The return type, the parameter-type-list, the ref-qualifier, the cv-qualifier-seq, and the exception specification, but not the default arguments ([dcl.fct.default]) or the trailing requires-clause ([dcl.decl]), are part of the function type.
[Note
:
Function types are checked during the assignments and initializations of pointers to functions, references to functions, and pointers to member functions.
end note
]
[Example
:
The declaration
int fseek(FILE*, long, int);
declares a function taking three arguments of the specified types, and returning int ([dcl.type]).
end example
]
A single name can be used for several different functions in a single scope; this is function overloading ([over]).
All declarations for a function shall have equivalent return types, parameter-type-lists, and requires-clauses ([temp.over.link]).
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.
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
:
typedef void F();
F  fv;              // OK: equivalent to void fv();
F  fv { }           // ill-formed
void fv() { }       // OK: definition of fv
end example
]
An identifier can optionally be provided as a parameter name; if present in a function definition ([dcl.fct.def]), it names a parameter.
[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 its function declarator because that is the extent of its potential scope ([basic.scope.param]).
end note
]
[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 integer 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.
end example
]
[Note
:
Typedefs and trailing-return-types 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);
or
auto fpif(int)->int(*)(int);
A trailing-return-type is most useful for a type that would be more complicated to specify before the declarator-id:
template <class T, class U> auto add(T t, U u) -> decltype(t + u);
rather than
template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
end note
]
A non-template function is a function that is not a function template specialization.
[Note
:
A function template is not a function.
end note
]
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration.
When it is part of a parameter-declaration-clause, the parameter-declaration declares a function parameter pack ([temp.variadic]).
Otherwise, the parameter-declaration is part of a template-parameter-list and declares a template parameter pack; see [temp.param].
A function parameter pack is a pack expansion ([temp.variadic]).
[Example
:
template<typename... T> void f(T (* ...t)(int, int));

int add(int, int);
float subtract(int, int);

void g() {
  f(add, subtract);
}
end example
]
There is a syntactic ambiguity when an ellipsis occurs at the end of a parameter-declaration-clause without a preceding comma.
In this case, the ellipsis is parsed as part of the abstract-declarator if the type of the parameter either names a template parameter pack that has not been expanded or contains auto; otherwise, it is parsed as part of the parameter-declaration-clause.97
As indicated by syntax, cv-qualifiers are a significant component in function return types.
One can explicitly disambiguate the parse either by introducing a comma (so the ellipsis will be parsed as part of the parameter-declaration-clause) or by introducing a name for the parameter (so the ellipsis will be parsed as part of the declarator-id).

9.2.3.6 Default arguments [dcl.fct.default]

If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument.
[Note
:
Default arguments will be used in calls where trailing arguments are missing ([expr.call]).
end note
]
[Example
:
The declaration
void point(int = 3, int = 4);
declares a function that can be called with zero, one, or two arguments 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.
end example
]
A default argument shall be specified only in the parameter-declaration-clause of a function declaration or lambda-declarator or in a template-parameter; in the latter case, the initializer-clause shall be an assignment-expression.
A default argument shall not be specified for a template parameter pack or a function parameter pack.
If it is specified in a parameter-declaration-clause, it shall not occur within a declarator or abstract-declarator of a parameter-declaration.98
For non-template functions, default arguments can be added in later declarations of a function in the same scope.
Declarations in different scopes have completely distinct sets of default arguments.
That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa.
In a given function declaration, each parameter subsequent to a parameter with a default argument shall have a default argument supplied in this or a previous declaration, unless the parameter was expanded from a parameter pack, or shall be a function parameter pack.
A default argument shall not be redefined by a later declaration (not even to the same value).
[Example
:
void g(int = 0, ...);           // OK, ellipsis is not a parameter so it can follow
                                // a parameter with a default argument
void f(int, int);
void f(int, int = 7);
void h() {
  f(3);                         // OK, calls f(3, 7)
  void f(int = 1, int);         // error: does not use default from surrounding scope
}
void m() {
  void f(int, int);             // has no defaults
  f(4);                         // error: wrong number of arguments
  void f(int, int = 5);         // OK
  f(4);                         // OK, calls f(4, 5);
  void f(int, int = 5);         // error: cannot redefine, even to same value
}
void n() {
  f(6);                         // OK, calls f(6, 7)
}
template<class ... T> struct C {
  void f(int n = 0, T...);
};
C<int> c;                       // OK, instantiates declaration void C​::​f(int n = 0, int)
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].
If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.
The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics ([dcl.init]).
The names in the default argument are bound, and the semantic constraints are checked, at the point where the default argument appears.
Name lookup and checking of semantic constraints for default arguments in function templates and in member functions of class templates are performed as described in [temp.inst].
[Example
:
In the following code, 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))
  }
}
end example
]
[Note
:
In member function declarations, names in default arguments are looked up as described in [basic.lookup.unqual].
Access checking applies to names in default arguments as described in [class.access].
end note
]
Except for member functions of class templates, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the member function declaration in the class definition; the program is ill-formed if a default constructor ([class.default.ctor]), copy or move constructor ([class.copy.ctor]), or copy or move assignment operator ([class.copy.assign]) is so declared.
Default arguments for a member function of a class template shall be specified on the initial declaration of the member function within the class template.
[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
]
[Note
:
A local variable cannot be odr-used ([basic.def.odr]) in a default argument.
end note
]
[Example
:
void f() {
  int i;
  extern void g(int x = i);         // error
  extern void h(int x = sizeof(i)); // OK
  // ...
}
end example
]
[Note
:
The keyword this may not appear in a default argument of a member function; see [expr.prim.this].
[Example
:
class A {
  void f(A* p = this) { }           // error
};
end example
]
end note
]
A default argument is evaluated each time the function is called with no argument for the corresponding parameter.
A parameter shall not appear as a potentially-evaluated expression in a default argument.
Parameters of a function declared before a default argument 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));    // OK, unevaluated operand
end example
]
A non-static member shall not appear in a default argument 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 following example is ill-formed because no object is supplied for the non-static member X::a used as an initializer.
int b;
class X {
  int a;
  int mem1(int i = a);              // error: non-static 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].
end example
]
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();                      // OK, 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, 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.
A 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
]
This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.

9.3 Initializers [dcl.init]

The process of initialization described in this subclause applies to all initializations regardless of syntactic context, including the initialization of a function parameter ([expr.call]), the initialization of a return value ([stmt.return]), or when an initializer follows a declarator.
initializer:
	brace-or-equal-initializer
	( expression-list )
brace-or-equal-initializer:
	= initializer-clause
	braced-init-list
initializer-clause:
	assignment-expression
	braced-init-list
braced-init-list:
	{ initializer-list , }
	{ designated-initializer-list , }
	{ }
initializer-list:
	initializer-clause ...
	initializer-list , initializer-clause ...
designated-initializer-list:
	designated-initializer-clause
	designated-initializer-list , designated-initializer-clause
designated-initializer-clause:
	designator brace-or-equal-initializer
designator:
	. identifier
expr-or-braced-init-list:
	expression
	braced-init-list
[Note
:
The rules in this subclause apply even if the grammar permits only the brace-or-equal-initializer form of initializer in a given context.
end note
]
Except for objects declared with the constexpr specifier, for which see [dcl.constexpr], an initializer in the definition of a variable can consist of arbitrary expressions involving literals and previously declared variables and functions, regardless of the variable's storage duration.
[Example
:
int f(int);
int a = 2;
int b = f(a);
int c(b);
end example
]
[Note
:
Default arguments are more restricted; see [dcl.fct.default].
end note
]
[Note
:
The order of initialization of variables with static storage duration is described in [basic.start] and [stmt.dcl].
end note
]
A declaration of a block-scope variable with external or internal linkage that has an initializer is ill-formed.
To zero-initialize an object or reference of type T means:
  • if T is a scalar type, the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;99
  • if T is a (possibly cv-qualified) non-union class type, its padding bits are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;
  • if T is a (possibly cv-qualified) union type, its padding bits are initialized to zero bits and the object's first non-static named data member is zero-initialized;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.
To default-initialize an object of type T means:
  • If T is a (possibly cv-qualified) class type ([class]), constructors are considered.
    The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]).
    The constructor thus selected is called, with an empty argument list, to initialize the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.
A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if
  • each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible,
  • if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,
  • if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and
  • each potentially constructed base class of T is const-default-constructible.
If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.
To value-initialize an object of type T means:
  • if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
  • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.
A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed.
[Note
:
Every object of static storage duration is zero-initialized at program startup before any other initialization takes place.
In some cases, additional initialization is done later.
end note
]
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
[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 permitted in certain other initialization contexts ([expr.new], [expr.type.conv], [class.base.init]).
end note
]
If no initializer is specified for an object, the object is default-initialized.
When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced ([expr.ass]).
[Note
:
Objects with static or thread storage duration are zero-initialized, see [basic.start.static].
end note
]
If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:
  • If an indeterminate value of unsigned narrow character type ([basic.fundamental]) or std::byte type ([cstddef.syn]) is produced by the evaluation of: then the result of the operation is an indeterminate value.
  • If an indeterminate value of unsigned narrow character type or std::byte type is produced by the evaluation of the right operand of a simple assignment operator ([expr.ass]) whose first operand is an lvalue of unsigned narrow character type or std::byte type, an indeterminate value replaces the value of the object referred to by the left operand.
  • If an indeterminate value of unsigned narrow character type is produced by the evaluation of the initialization expression when initializing an object of unsigned narrow character type, that object is initialized to an indeterminate value.
  • If an indeterminate value of unsigned narrow character type or std::byte type is produced by the evaluation of the initialization expression when initializing an object of std::byte type, that object is initialized to an indeterminate value.
[Example
:
  int f(bool b) {
    unsigned char c;
    unsigned char d = c;        // OK, d has an indeterminate value
    int e = d;                  // undefined behavior
    return b ? d : 0;           // undefined behavior if b is true
  }
end example
]
An 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
]
If the entity being initialized does not have class type, the expression-list in a parenthesized initializer shall be a single expression.
The initialization that occurs in the = form of a brace-or-equal-initializer or condition ([stmt.select]), as well as in argument passing, function return, throwing an exception ([except.throw]), handling an exception ([except.handle]), and aggregate member initialization ([dcl.init.aggr]), is called copy-initialization.
[Note
:
Copy-initialization may invoke a move ([class.copy.ctor]).
end note
]
The initialization that occurs is called direct-initialization.
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 initializer is not a single (possibly parenthesized) expression, the source type is not defined.
  • If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized ([dcl.init.list]).
  • If the destination type is a reference type, see [dcl.init.ref].
  • If the destination type is an array of characters, an array of char16_­t, an array of char32_­t, or an array of wchar_­t, and the initializer is a string literal, see [dcl.init.string].
  • If the initializer is (), the object is value-initialized.
  • Otherwise, if the destination type is an array, the program is ill-formed.
  • If the destination type is a (possibly cv-qualified) class type:
    • If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.
      [Example
      :
      T x = T(T(T())); calls the T default constructor to initialize x.
      end example
      ]
    • Otherwise, 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 destination, constructors are considered.
      The applicable constructors are enumerated ([over.match.ctor]), and the best one is chosen through overload resolution ([over.match]).
      The constructor so selected is called to initialize the object, with the initializer expression or expression-list 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), user-defined conversions that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in [over.match.copy], and the best one is chosen through overload resolution ([over.match]).
      If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
      The function selected is called with the initializer expression as its argument; if the function is a constructor, the call is a prvalue of the cv-unqualified version of the destination type whose result object is initialized by the constructor.
      The call is used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
  • Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered.
    The applicable conversion 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.
  • Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression.
    Standard conversions ([conv]) will be used, if necessary, to convert the initializer expression to the cv-unqualified version of the destination type; no user-defined conversions are considered.
    If the conversion cannot be done, the initialization is ill-formed.
    When initializing a bit-field with a value that it cannot represent, the resulting value of the bit-field is implementation-defined.
    [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
    ]
An initializer-clause followed by an ellipsis is a pack expansion ([temp.variadic]).
If the initializer is a parenthesized expression-list, the expressions are evaluated in the order specified for function calls ([expr.call]).
The same identifier shall not appear in multiple designators of a designated-initializer-list.
An object whose initialization has completed is deemed to be constructed, even if no constructor of the object's class is invoked for the initialization.
[Note
:
Such an object might have been value-initialized or initialized by aggregate initialization ([dcl.init.aggr]) or by an inherited constructor ([class.inhctor.init]).
end note
]
A declaration that specifies the initialization of a variable, whether from an explicit initializer or by default-initialization, is called the initializing declaration of that variable.
[Note
:
In most cases this is the defining declaration ([basic.def]) of the variable, but the initializing declaration of a non-inline static data member ([class.static.data]) might be the declaration within the class definition and not the definition at namespace scope.
end note
]
As specified in [conv.ptr], converting an integer literal whose value is 0 to a pointer type results in a null pointer value.

9.3.1 Aggregates [dcl.init.aggr]

An aggregate is an array or a class ([class]) with
[Note
:
Aggregate initialization does not allow accessing protected and private base class' members or constructors.
end note
]
The elements of an aggregate are:
  • for an array, the array elements in increasing subscript order, or
  • for a class, the direct base classes in declaration order, followed by the direct non-static data members ([class.mem]) that are not members of an anonymous union, in declaration order.
When an aggregate is initialized by an initializer list as specified in [dcl.init.list], the elements of the initializer list are taken as initializers for the elements of the aggregate.
The explicitly initialized elements of the aggregate are determined as follows:
  • If the initializer list is a designated-initializer-list, the aggregate shall be of class type, the identifier in each designator shall name a direct non-static data member of the class, and the explicitly initialized elements of the aggregate are the elements that are, or contain, those members.
  • If the initializer list is an initializer-list, the explicitly initialized elements of the aggregate are the first n elements of the aggregate, where n is the number of elements in the initializer list.
  • Otherwise, the initializer list must be {}, and there are no explicitly initialized elements.
For each explicitly initialized element:
[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.
struct base1 { int b1, b2 = 42; };
struct base2 {
  base2() {
    b3 = 42;
  }
  int b3;
};
struct derived : base1, base2 {
  int d;
};

derived d1{{1, 2}, {}, 4};
derived d2{{}, {}, 4};
initializes d1.b1 with 1, d1.b2 with 2, d1.b3 with 42, d1.d with 4, and d2.b1 with 0, d2.b2 with 42, d2.b3 with 42, d2.d with 4.
end example
]
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
  • If the element has a default member initializer ([class.mem]), the element is initialized from that initializer.
  • Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
  • Otherwise, the program is ill-formed.
If the aggregate is a union and the initializer list is empty, then
  • if any variant member has a default member initializer, that member is initialized from its default member initializer;
  • otherwise, the first member of the union (if any) is copy-initialized from an empty initializer list.
[Example
:
struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", ss.c with the value of an expression of the form int{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, 's'), and in
struct X { int i, j, k = 42; };
X a[] = { 1, 2, 3, 4, 5, 6 };
X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };
a and b have the same value
struct A {
  string a;
  int b = 42;
  int c = -1;
};
A{.c=21} has the following steps:
  • Initialize a with {}
  • Initialize b with = 42
  • Initialize c with = 21
end example
]
The initializations of the elements of the aggregate are evaluated in the element order.
That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.
An aggregate that is a class can also be initialized with a single expression not enclosed in braces, as described in [dcl.init].
The destructor for each element of class type is potentially invoked ([class.dtor]) from the context where the aggregate initialization occurs.
[Note
:
This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([except.ctor]).
end note
]
An array of unknown bound initialized with a brace-enclosed initializer-list containing n initializer-clauses, 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.
end example
]
An empty initializer list {} shall not be used as the initializer-clause for an array of unknown bound.100
[Note
:
A default member initializer does not determine the bound for a member array of unknown bound.
Since the default member initializer is ignored if a suitable mem-initializer is present ([class.base.init]), the default member initializer is not considered to initialize the array of unknown bound.
[Example
:
struct S {
  int y[] = { 0 };          // error: non-static data member of incomplete type
};
end example
]
end note
]
[Note
:
Static data members, non-static data members of anonymous union members, and unnamed bit-fields are not considered elements of the aggregate.
[Example
:
struct A {
  int i;
  static int s;
  int j;
  int :17;
  int k;
} a = { 1, 2, 3 };
Here, the second initializer 2 initializes a.j and not the static data member A::s, and the third initializer 3 initializes a.k and not the unnamed bit-field before it.
end example
]
end note
]
An initializer-list is ill-formed if the number of initializer-clauses exceeds the number of elements of the aggregate.
[Example
:
char cv[4] = { 'a', 's', 'd', 'f', 0 };     // error
is ill-formed.
end example
]
If a reference member is initialized from its default member initializer and a potentially-evaluated subexpression thereof is an aggregate initialization that would use that default member initializer, the program is ill-formed.
[Example
:
  struct A;
  extern A a;
  struct A {
    const A& a1 { A{a,a} };     // OK
    const A& a2 { A{} };        // error
  };
  A a{a,a};                     // OK
end example
]
If an aggregate class C contains a subaggregate element e with no elements, the initializer-clause for e shall not be omitted from an initializer-list for an object of type C unless the initializer-clauses for all elements of C following e are also omitted.
[Example
:
struct S { } s;
struct A {
  S s1;
  int i1;
  S s2;
  int i2;
  S s3;
  int i3;
} a = {
  { },              // Required initialization
  0,
  s,                // Required initialization
  0
};                  // Initialization not required for A​::​s3 because A​::​i3 is also not initialized
end example
]
When initializing a multi-dimensional array, the initializer-clauses initialize 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.
end example
]
Braces can be elided in an initializer-list as follows.
If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the elements of a subaggregate; it is erroneous for there to be more initializer-clauses than elements.
If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the elements of the subaggregate; any remaining initializer-clauses are left to initialize the next element of the aggregate of which the current subaggregate is an element.
[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 explicitly initialized with an expression of the form float(), that is, are initialized with 0.0.
In the following example, braces in the initializer-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 example
]
All implicit type conversions ([conv]) are considered when initializing the element with an assignment-expression.
If the assignment-expression can initialize an element, the element is initialized.
Otherwise, if the element is itself a subaggregate, brace elision is assumed and the assignment-expression is considered for the initialization of the first element of the subaggregate.
[Note
:
As specified above, brace elision cannot apply to subaggregates with no elements; an initializer-clause for the entire subobject is required.
end note
]
[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-clause for b.a1.i.
b.a1.i is initialized with 4, b.a2 is initialized with a, b.z is initialized with whatever a.operator int() returns.
end example
]
[Note
:
An aggregate array or an aggregate class may contain elements of a class type with a user-declared constructor ([class.ctor]).
Initialization of these aggregate objects is described in [class.expl.init].
end note
]
[Note
:
Whether the initialization of aggregates with static storage duration is static or dynamic is specified in [basic.start.static], [basic.start.dynamic], and [stmt.dcl].
end note
]
When a union is initialized with an initializer list, there shall not be more than one explicitly initialized element.
[Example
:
union u { int a; const char* b; };
u a = { 1 };
u b = a;
u c = 1;                        // error
u d = { 0, "asdf" };            // error
u e = { "asdf" };               // error
u f = { .b = "asdf" };
u g = { .a = 1, .b = "asdf" };  // error
end example
]
[Note
:
As described above, the braces around the initializer-clause for a union member can be omitted if the union is a member of another aggregate.
end note
]
The syntax provides for empty initializer lists, but nonetheless C++ does not have zero length arrays.

9.3.2 Character arrays [dcl.init.string]

An array of narrow character type, char16_­t array, char32_­t array, or wchar_­t array can be initialized by a narrow string literal, char16_­t string literal, char32_­t string literal, or wide string literal, respectively, or by an appropriately-typed string literal enclosed in braces ([lex.string]).
Successive characters of the value of the string literal initialize the elements 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.
end example
]
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'.
end example
]
If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized ([dcl.init]).

9.3.3 References [dcl.init.ref]

A variable whose declared type is “reference to type T” ([dcl.ref]) shall be initialized.
[Example
:
int g(int) noexcept;
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
]
A reference cannot be changed to refer to another object after initialization.
[Note
:
Assignment to a reference assigns to the object referred to by the reference ([expr.ass]).
end note
]
Argument passing ([expr.call]) and function value return ([stmt.return]) are initializations.
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 definition ([class.mem]), and where the extern specifier is explicitly used.
[Example
:
int& r1;                        // error: initializer missing
extern int& r2;                 // OK
end example
]
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, or
  • T2 is “noexcept function” and T1 is “function”, where the function types are otherwise the same,
and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2.
In all cases where the reference-related or reference-compatible relationship of two types is used to establish the validity of a reference binding, and T1 is a base class of T2, a program that necessitates such a binding is ill-formed if T1 is an inaccessible ([class.access]) or ambiguous ([class.member.lookup]) base class of T2.
A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
  • If the reference is an lvalue reference and the initializer expression
    • is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2”, or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3101 (this conversion is selected by enumerating the applicable conversion functions ([over.match.ref]) and choosing the best one through overload resolution),
    then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).
    [Note
    :
    The usual lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done.
    end note
    ]
    [Example
    :
    double d = 2.0;
    double& rd = d;                 // rd refers to d
    const double& rcd = d;          // rcd refers to d
    
    struct A { };
    struct B : A { operator int&(); } b;
    A& ra = b;                      // ra refers to A subobject in b
    const A& rca = b;               // rca refers to A subobject in b
    int& ir = B();                  // ir refers to the result of B​::​operator int&
    
    end example
    ]
  • Otherwise, if the reference is an lvalue reference to a type that is not const-qualified or is volatile-qualified, the program is ill-formed.
    [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
    ]
  • Otherwise, if the initializer expression
    • is an rvalue (but not a bit-field) or function lvalue and “cv1 T1” is reference-compatible with “cv2 T2”, or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an rvalue or function lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3” (see [over.match.ref]),
    then the value of the initializer expression in the first case and the result of the conversion in the second case is called the converted initializer.
    If the converted initializer is a prvalue, its type T4 is adjusted to type “cv1 T4” ([conv.qual]) and the temporary materialization conversion ([conv.rval]) is applied.
    In any case, the reference is bound to the resulting glvalue (or to an appropriate base class subobject).
    [Example
    :
    struct A { };
    struct B : A { } b;
    extern B f();
    const A& rca2 = f();                // bound to the A subobject of the B rvalue.
    A&& rra = f();                      // same as above
    struct X {
      operator B();
      operator int&();
    } x;
    const A& r = x;                     // bound to the A subobject of the result of the conversion
    int i2 = 42;
    int&& rri = static_cast<int&&>(i2); // bound directly to i2
    B&& rrb = x;                        // bound directly to the result of operator B
    
    end example
    ]
  • Otherwise:
    • If T1 or T2 is a class type and T1 is not reference-related to T2, user-defined conversions are considered using the rules for copy-initialization of an object of type “cv1 T1” by user-defined conversion ([dcl.init], [over.match.copy], [over.match.conv]); the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed.
      The result of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference.
      For this direct-initialization, user-defined conversions are not considered.
    • Otherwise, the initializer expression is implicitly converted to a prvalue of type “cv1 T1.
      The temporary materialization conversion is applied and the reference is bound to the result.
    If T1 is reference-related to T2:
    • cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2; and
    • if the reference is an rvalue reference, the initializer expression shall not be an lvalue.
    [Example
    :
    struct Banana { };
    struct Enigma { operator const Banana(); };
    struct Alaska { operator Banana&(); };
    void enigmatic() {
      typedef const Banana ConstBanana;
      Banana &&banana1 = ConstBanana(); // ill-formed
      Banana &&banana2 = Enigma();      // ill-formed
      Banana &&banana3 = Alaska();      // ill-formed
    }
    
    const double& rcd2 = 2;             // rcd2 refers to temporary with value 2.0
    double&& rrd = 2;                   // rrd refers to temporary with value 2.0
    const volatile int cvi = 1;
    const int& r2 = cvi;                // error: cv-qualifier dropped
    struct A { operator volatile int&(); } a;
    const int& r3 = a;                  // error: cv-qualifier dropped
                                        // from result of conversion function
    double d2 = 1.0;
    double&& rrd2 = d2;                 // error: initializer is lvalue of related type
    struct X { operator int&(); };
    int&& rri2 = X();                   // error: result of conversion function is lvalue of related type
    int i3 = 2;
    double&& rrd3 = i3;                 // rrd3 refers to temporary with value 2.0
    
    end example
    ]
In all cases except the last (i.e., implicitly converting the initializer expression to the referenced type), the reference is said to bind directly to the initializer expression.
[Note
:
[class.temporary] describes the lifetime of temporaries bound to references.
end note
]
This requires a conversion function ([class.conv.fct]) returning a reference type.

9.3.4 List-initialization [dcl.init.list]

List-initialization is initialization of an object or reference from a braced-init-list.
Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the initializer-list or designated-initializer-clauses of the designated-initializer-list are called the elements of the initializer list.
An initializer list may be empty.
List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.
[Note
:
List-initialization can be used
[Example
:
int a = {1};
std::complex<double> z{1,2};
new std::vector<std::string>{"once", "upon", "a", "time"};  // 4 string elements
f( {"Nicholas","Annemarie"} );  // pass list of two elements
return { "Norah" };             // return list of one element
int* e {};                      // initialization to zero / null pointer
x = double{1};                  // explicitly construct a double
std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };
end example
]
end note
]
A constructor is an initializer-list constructor if its first parameter is of type std::initializer_­list<E> or reference to possibly cv-qualified std::initializer_­list<E> for some type E, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).
[Note
:
Initializer-list constructors are favored over other constructors in list-initialization ([over.match.list]).
Passing an initializer list as the argument to the constructor template template<class T> C(T) of a class C does not create an initializer-list constructor, because an initializer list argument causes the corresponding parameter to be a non-deduced context ([temp.deduct.call]).
end note
]
The template std::initializer_­list is not predefined; if the header <initializer_­list> is not included prior to a use of std::initializer_­list — even an implicit use in which the type is not named ([dcl.spec.auto]) — the program is ill-formed.
List-initialization of an object or reference of type T is defined as follows:
  • If the braced-init-list contains a designated-initializer-list, T shall be an aggregate class.
    The ordered identifiers in the designators of the designated-initializer-list shall form a subsequence of the ordered identifiers in the direct non-static data members of T.
    Aggregate initialization is performed ([dcl.init.aggr]).
    [Example
    :
    struct A { int x; int y; int z; };
    A a{.y = 2, .x = 1};                // error: designator order does not match declaration order
    A b{.x = 1, .z = 2};                // OK, b.y initialized to 0
    
    end example
    ]
  • If T is an aggregate class and the initializer list has a single element of type cv U, where U is T or a class derived from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
  • Otherwise, if T is a character array and the initializer list has a single element that is an appropriately-typed string literal ([dcl.init.string]), initialization is performed as described in that subclause.
  • Otherwise, if T is an aggregate, aggregate initialization is performed ([dcl.init.aggr]).
    [Example
    :
    double ad[] = { 1, 2.0 };           // OK
    int ai[] = { 1, 2.0 };              // error: narrowing
    
    struct S2 {
      int m1;
      double m2, m3;
    };
    S2 s21 = { 1, 2, 3.0 };             // OK
    S2 s22 { 1.0, 2, 3 };               // error: narrowing
    S2 s23 { };                         // OK: default to 0,0,0
    
    end example
    ]
  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • Otherwise, if T is a specialization of std::initializer_­list<E>, the object is constructed as described below.
  • Otherwise, if T is a class type, constructors are considered.
    The applicable constructors are enumerated and the best one is chosen through overload resolution ([over.match], [over.match.list]).
    If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
    [Example
    :
    struct S {
      S(std::initializer_list<double>); // #1
      S(std::initializer_list<int>);    // #2
      S();                              // #3
      // ...
    };
    S s1 = { 1.0, 2.0, 3.0 };           // invoke #1
    S s2 = { 1, 2, 3 };                 // invoke #2
    S s3 = { };                         // invoke #3
    
    end example
    ]
    [Example
    :
    struct Map {
      Map(std::initializer_list<std::pair<std::string,int>>);
    };
    Map ship = {{"Sophie",14}, {"Surprise",28}};
    
    end example
    ]
    [Example
    :
    struct S {
      // no initializer-list constructors
      S(int, double, double);           // #1
      S();                              // #2
      // ...
    };
    S s1 = { 1, 2, 3.0 };               // OK: invoke #1
    S s2 { 1.0, 2, 3 };                 // error: narrowing
    S s3 { };                           // OK: invoke #2
    
    end example
    ]
  • Otherwise, if T is an enumeration with a fixed underlying type ([dcl.enum]), the initializer-list has a single element v, and the initialization is direct-list-initialization, the object is initialized with the value T(v) ([expr.type.conv]); if a narrowing conversion is required to convert v to the underlying type of T, the program is ill-formed.
    [Example
    :
    enum byte : unsigned char { };
    byte b { 42 };                      // OK
    byte c = { 42 };                    // error
    byte d = byte{ 42 };                // OK; same value as b
    byte e { -1 };                      // error
    
    struct A { byte b; };
    A a1 = { { 42 } };                  // error
    A a2 = { byte{ 42 } };              // OK
    
    void f(byte);
    f({ 42 });                          // error
    
    enum class Handle : uint32_t { Invalid = 0 };
    Handle h { 42 };                    // OK
    
    end example
    ]
  • Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization); if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.
    [Example
    :
    int x1 {2};                         // OK
    int x2 {2.0};                       // error: narrowing
    
    end example
    ]
  • Otherwise, if T is a reference type, a prvalue of the type referenced by T is generated.
    The prvalue initializes its result object by copy-list-initialization or direct-list-initialization, depending on the kind of initialization for the reference.
    The prvalue is then used to direct-initialize the reference.
    [Note
    :
    As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type.
    end note
    ]
    [Example
    :
    struct S {
      S(std::initializer_list<double>); // #1
      S(const std::string&);            // #2
      // ...
    };
    const S& r1 = { 1, 2, 3.0 };        // OK: invoke #1
    const S& r2 { "Spinach" };          // OK: invoke #2
    S& r3 = { 1, 2, 3 };                // error: initializer is not an lvalue
    const int& i1 = { 1 };              // OK
    const int& i2 = { 1.1 };            // error: narrowing
    const int (&iar)[2] = { 1, 2 };     // OK: iar is bound to temporary array
    
    end example
    ]
  • Otherwise, if the initializer list has no elements, the object is value-initialized.
    [Example
    :
    int** pp {};                        // initialized to null pointer
    
    end example
    ]
  • Otherwise, the program is ill-formed.
    [Example
    :
    struct A { int i; int j; };
    A a1 { 1, 2 };                      // aggregate initialization
    A a2 { 1.2 };                       // error: narrowing
    struct B {
      B(std::initializer_list<int>);
    };
    B b1 { 1, 2 };                      // creates initializer_­list<int> and calls constructor
    B b2 { 1, 2.0 };                    // error: narrowing
    struct C {
      C(int i, double j);
    };
    C c1 = { 1, 2.2 };                  // calls constructor with arguments (1, 2.2)
    C c2 = { 1.1, 2 };                  // error: narrowing
    
    int j { 1 };                        // initialize to 1
    int k { };                          // initialize to 0
    
    end example
    ]
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions ([temp.variadic]), are evaluated in the order in which they appear.
That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.
[Note
:
This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call.
end note
]
An object of type std::initializer_­list<E> is constructed from an initializer list as if the implementation generated and materialized ([conv.rval]) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list.
Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_­list<E> object is constructed to refer to that array.
[Note
:
A constructor or conversion function selected for the copy shall be accessible ([class.access]) in the context of the initializer list.
end note
]
If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.
[Example
:
struct X {
  X(std::initializer_list<double> v);
};
X x{ 1,2,3 };
The initialization will be implemented in a way roughly equivalent to this:
const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));
assuming that the implementation can construct an initializer_­list object with a pair of pointers.
end example
]
The array has the same lifetime as any other temporary object ([class.temporary]), except that initializing an initializer_­list object from the array extends the lifetime of the array exactly like binding a reference to a temporary.
[Example
:
typedef std::complex<double> cmplx;
std::vector<cmplx> v1 = { 1, 2, 3 };

void f() {
  std::vector<cmplx> v2{ 1, 2, 3 };
  std::initializer_list<int> i3 = { 1, 2, 3 };
}

struct A {
  std::initializer_list<int> i4;
  A() : i4{ 1, 2, 3 } {}            // ill-formed, would create a dangling reference
};
For v1 and v2, the initializer_­list object is a parameter in a function call, so the array created for { 1, 2, 3 } has full-expression lifetime.
For i3, the initializer_­list object is a variable, so the array persists for the lifetime of the variable.
For i4, the initializer_­list object is initialized in the constructor's ctor-initializer as if by binding a temporary array to a reference member, so the program is ill-formed ([class.base.init]).
end example
]
[Note
:
The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer could be so allocated.
end note
]
A narrowing conversion is an implicit conversion
  • from a floating-point type to an integer type, or
  • from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or
  • from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
  • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.
[Note
:
As indicated above, such conversions are not allowed at the top level in list-initializations.
end note
]
[Example
:
int x = 999;                    // x is not a constant expression
const int y = 999;
const int z = 99;
char c1 = x;                    // OK, though it might narrow (in this case, it does narrow)
char c2{x};                     // error: might narrow
char c3{y};                     // error: narrows (assuming char is 8 bits)
char c4{z};                     // OK: no narrowing needed
unsigned char uc1 = {5};        // OK: no narrowing needed
unsigned char uc2 = {-1};       // error: narrows
unsigned int ui1 = {-1};        // error: narrows
signed int si1 =
  { (unsigned int)-1 };         // error: narrows
int ii = {2.0};                 // error: narrows
float f1 { x };                 // error: might narrow
float f2 { 7 };                 // OK: 7 can be exactly represented as a float
int f(int);
int a[] = { 2, f(2), f(2.0) };  // OK: the double-to-int conversion is not at the top level
end example
]

9.4 Function definitions [dcl.fct.def]

9.4.1 In general [dcl.fct.def.general]

Function definitions have the form
function-definition:
	attribute-specifier-seq decl-specifier-seq declarator virt-specifier-seq function-body
	attribute-specifier-seq decl-specifier-seq declarator requires-clause function-body
function-body:
	ctor-initializer compound-statement
	function-try-block
	= default ;
	= delete ;
Any informal reference to the body of a function should be interpreted as a reference to the non-terminal function-body.
The optional attribute-specifier-seq in a function-definition appertains to the function.
In a function-definition, either void declarator ; or declarator ; shall be a well-formed function declaration as described in [dcl.fct].
A function shall be defined only in namespace or class scope.
The type of a parameter or the return type for a function definition shall not be an incomplete or abstract (possibly cv-qualified) class type in the context of the function definition unless the function is deleted ([dcl.fct.def.delete]).
[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.
end example
]
A ctor-initializer is used only in a constructor; see [class.ctor] and [class.init].
[Note
:
A cv-qualifier-seq affects the type of this in the body of a member function; see [dcl.ref].
end note
]
[Note
:
Unused parameters need not be named.
For example,
void print(int a, int) {
  std::printf("a = %d\n",a);
}
end note
]
In the function-body, a function-local predefined variable denotes a block-scope object of static storage duration that is implicitly defined (see [basic.scope.block]).
The function-local predefined variable _­_­func_­_­ is defined as if a definition of the form
static const char __func__[] = "function-name";
had been provided, where function-name is an implementation-defined string.
It is unspecified whether such a variable has an address distinct from that of any other object in the program.102
[Example
:
struct S {
  S() : s(__func__) { }             // OK
  const char* s;
};
void f(const char* s = __func__);   // error: _­_­func_­_­ is undeclared
end example
]
Implementations are permitted to provide additional predefined variables with names that are reserved to the implementation ([lex.name]).
If a predefined variable is not odr-used ([basic.def.odr]), its string value need not be present in the program image.

9.4.2 Explicitly-defaulted functions [dcl.fct.def.default]

A function definition whose function-body is of the form = default ; is called an explicitly-defaulted definition.
A function that is explicitly defaulted shall
The type T of an explicitly defaulted function F is allowed to differ from the type T it would have had if it were implicitly declared, as follows:
  • T and T may have differing ref-qualifiers; and
  • if T has a parameter of type const C&, the corresponding parameter of T may be of type C&.
If T differs from T in any other way, then:
  • if F is an assignment operator, and the return type of T differs from the return type of T or T's parameter type is not a reference, the program is ill-formed;
  • otherwise, if F is explicitly defaulted on its first declaration, it is defined as deleted;
  • otherwise, the program is ill-formed.
An explicitly-defaulted function that is not defined as deleted may be declared constexpr only if it would have been implicitly declared as constexpr.
If a function is explicitly defaulted on its first declaration, it is implicitly considered to be constexpr if the implicit declaration would be.
[Example
:
struct S {
  constexpr S() = default;              // ill-formed: implicit S() is not constexpr
  S(int a = 0) = default;               // ill-formed: default argument
  void operator=(const S&) = default;   // ill-formed: non-matching return type
  ~S() noexcept(false) = default;       // deleted: exception specification does not match
private:
  int i;
  S(S&);                                // OK: private copy constructor
};
S::S(S&) = default;                     // OK: defines copy constructor
end example
]
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted.
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed.
[Note
:
Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base.
end note
]
[Example
:
struct trivial {
  trivial() = default;
  trivial(const trivial&) = default;
  trivial(trivial&&) = default;
  trivial& operator=(const trivial&) = default;
  trivial& operator=(trivial&&) = default;
  ~trivial() = default;
};

struct nontrivial1 {
  nontrivial1();
};
nontrivial1::nontrivial1() = default;   // not first declaration
end example
]

9.4.3 Deleted definitions [dcl.fct.def.delete]

A function definition whose function-body is of the form = delete ; is called a deleted definition.
A function with a deleted definition is also called a deleted function.
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
[Note
:
This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function.
It applies even for references in expressions that are not potentially-evaluated.
If a function is overloaded, it is referenced only if the function is selected by overload resolution.
The implicit odr-use ([basic.def.odr]) of a virtual function does not, by itself, constitute a reference.
end note
]
[Example
:
One can prevent default initialization and initialization by non-doubles with
struct onlydouble {
  onlydouble() = delete;                // OK, but redundant
  template<class T>
    onlydouble(T) = delete;
  onlydouble(double);
};
end example
]
[Example
:
One can prevent use of a class in certain new-expressions by using deleted definitions of a user-declared operator new for that class.
struct sometype {
  void* operator new(std::size_t) = delete;
  void* operator new[](std::size_t) = delete;
};
sometype* p = new sometype;     // error, deleted class operator new
sometype* q = new sometype[3];  // error, deleted class operator new[]
end example
]
[Example
:
One can make a class uncopyable, i.e., move-only, by using deleted definitions of the copy constructor and copy assignment operator, and then providing defaulted definitions of the move constructor and move assignment operator.
struct moveonly {
  moveonly() = default;
  moveonly(const moveonly&) = delete;
  moveonly(moveonly&&) = default;
  moveonly& operator=(const moveonly&) = delete;
  moveonly& operator=(moveonly&&) = default;
  ~moveonly() = default;
};
moveonly* p;
moveonly q(*p);                 // error, deleted copy constructor
end example
]
A deleted function is implicitly an inline function ([dcl.inline]).
[Note
:
The one-definition rule ([basic.def.odr]) applies to deleted definitions.
end note
]
A deleted definition of a function shall be the first declaration of the function or, for an explicit specialization of a function template, the first declaration of that specialization.
An implicitly declared allocation or deallocation function ([basic.stc.dynamic]) shall not be defined as deleted.
[Example
:
struct sometype {
  sometype();
};
sometype::sometype() = delete;  // ill-formed; not first declaration
end example
]

9.5 Structured binding declarations [dcl.struct.bind]

A structured binding declaration introduces the identifiers v, v, v, .
Let cv denote the cv-qualifiers in the decl-specifier-seq.
First, a variable with a unique name e is introduced.
If the assignment-expression in the initializer has array type A and no ref-qualifier is present, e has type cv A and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
Otherwise, e is defined as-if by
attribute-specifier-seq decl-specifier-seq ref-qualifier e initializer ;
where the declaration is never interpreted as a function declaration and the parts of the declaration other than the declarator-id are taken from the corresponding structured binding declaration.
The type of the id-expression e is called E.
[Note
:
E is never a reference type ([expr.prop]).
end note
]
If the initializer refers to one of the names introduced by the structured binding declaration, the program is ill-formed.
If E is an array type with element type T, the number of elements in the identifier-list shall be equal to the number of elements of E.
Each v is the name of an lvalue that refers to the element i of the array and whose type is T; the referenced type is T.
[Note
:
The top-level cv-qualifiers of T are cv.
end note
]
[Example
:
  auto f() -> int(&)[2];
  auto [ x, y ] = f();          // x and y refer to elements in a copy of the array return value
  auto& [ xr, yr ] = f();       // xr and yr refer to elements in the array referred to by f's return value
end example
]
Otherwise, if the qualified-id std::tuple_­size<E> names a complete type, the expression std::tuple_­size<E>::value shall be a well-formed integral constant expression and the number of elements in the identifier-list shall be equal to the value of that expression.
Let i be an index prvalue of type std::size_­t corresponding to v.
The unqualified-id get is looked up in the scope of E by class member access lookup ([basic.lookup.classref]), and if that finds at least one declaration that is a function template whose first template parameter is a non-type parameter, the initializer is e.get<i>().
Otherwise, the initializer is get<i>(e), where get is looked up in the associated namespaces ([basic.lookup.argdep]).
In either case, get<i> is interpreted as a template-id.
[Note
:
Ordinary unqualified lookup ([basic.lookup.unqual]) is not performed.
end note
]
In either case, e is an lvalue if the type of the entity e is an lvalue reference and an xvalue otherwise.
Given the type T designated by std::tuple_­element<i, E>::type, variables are introduced with unique names r of type “reference to T” initialized with the initializer ([dcl.init.ref]), where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise.
Each v is the name of an lvalue of type T that refers to the object bound to r; the referenced type is T.
Otherwise, all of E's non-static data members shall be direct members of E or of the same base class of E, well-formed when named as e.name in the context of the structured binding, E shall not have an anonymous union member, and the number of elements in the identifier-list shall be equal to the number of non-static data members of E.
Designating the non-static data members of E as m, m, m, .
(in declaration order), each v is the name of an lvalue that refers to the member m of e and whose type is cv T, where T is the declared type of that member; the referenced type is cv T.
The lvalue is a bit-field if that member is a bit-field.
[Example
:
struct S { int x1 : 2; volatile double y1; };
S f();
const auto [ x, y ] = f();
The type of the id-expression x is “const int”, the type of the id-expression y is “const volatile double.
end example
]

9.6 Enumeration declarations [dcl.enum]

An enumeration is a distinct type ([basic.compound]) with named constants.
Its name becomes an enum-name within its scope.
enum-name:
	identifier
enum-specifier:
	enum-head { enumerator-list }
	enum-head { enumerator-list , }
enum-head:
	enum-key attribute-specifier-seq enum-head-name enum-base
enum-head-name:
	nested-name-specifier identifier
opaque-enum-declaration:
	enum-key attribute-specifier-seq nested-name-specifier identifier enum-base ;
enum-key:
	enum
	enum class
	enum struct
enum-base:
	: type-specifier-seq
enumerator-list:
	enumerator-definition
	enumerator-list , enumerator-definition
enumerator-definition:
	enumerator
	enumerator = constant-expression
enumerator:
	identifier attribute-specifier-seq
The optional attribute-specifier-seq in the enum-head and the opaque-enum-declaration appertains to the enumeration; the attributes in that attribute-specifier-seq are thereafter considered attributes of the enumeration whenever it is named.
A : following “enum nested-name-specifier identifier” within the decl-specifier-seq of a member-declaration is parsed as part of an enum-base.
[Note
:
This resolves a potential ambiguity between the declaration of an enumeration with an enum-base and the declaration of an unnamed bit-field of enumeration type.
[Example
:
   struct S {
     enum E : int {};
     enum E : int {};           // error: redeclaration of enumeration
   };
end example
]
end note
]
If an opaque-enum-declaration contains a nested-name-specifier, the declaration shall be an explicit specialization.
The enumeration type declared with an enum-key of only enum is an unscoped enumeration, and its enumerators are unscoped enumerators.
The enum-keys enum class and enum struct are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators.
The optional identifier shall not be omitted in the declaration of a scoped enumeration.
The type-specifier-seq of an enum-base shall name an integral type; any cv-qualification is ignored.
An opaque-enum-declaration declaring an unscoped enumeration shall not omit the enum-base.
The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required.
An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression.
If the first enumerator has no initializer, the value of the corresponding constant is zero.
An enumerator-definition without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator by one.
[Example
:
enum { a, b, c=0 };
enum { d, e, f=e+2 };
defines a, c, and d to be zero, b and e to be 1, and f to be 3.
end example
]
The optional attribute-specifier-seq in an enumerator appertains to that enumerator.
An opaque-enum-declaration is either a redeclaration of an enumeration in the current scope or a declaration of a new enumeration.
[Note
:
An enumeration declared by an opaque-enum-declaration has a fixed underlying type and is a complete type.
The list of enumerators can be provided in a later redeclaration with an enum-specifier.
end note
]
A scoped enumeration shall not be later redeclared as unscoped or with a different underlying type.
An unscoped enumeration shall not be later redeclared as scoped and each redeclaration shall include an enum-base specifying the same underlying type as in the original declaration.
If the enum-key is followed by a nested-name-specifier, the enum-specifier shall refer to an enumeration that was previously declared directly in the class or namespace to which the nested-name-specifier refers (i.e., neither inherited nor introduced by a using-declaration), and the enum-specifier shall appear in a namespace enclosing the previous declaration.
Each enumeration defines a type that is different from all other types.
Each enumeration also has an underlying type.
The underlying type can be explicitly specified using an enum-base.
For a scoped enumeration type, the underlying type is int if it is not explicitly specified.
In both of these cases, the underlying type is said to be fixed.
Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration.
If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definition shall be a converted constant expression of the underlying type.
If the underlying type is not fixed, the type of each enumerator prior to the closing brace is determined as follows:
  • If an initializer is specified for an enumerator, the constant-expression shall be an integral constant expression.
    If the expression has unscoped enumeration type, the enumerator has the underlying type of that enumeration type, otherwise it has the same type as the expression.
  • If no initializer is specified for the first enumerator, its type is an unspecified signed integral type.
  • Otherwise the type of the enumerator is the same as that of the preceding enumerator unless the incremented value is not representable in that type, in which case the type is an unspecified integral type sufficient to contain the incremented value.
    If no such type exists, the program is ill-formed.
An enumeration whose underlying type is fixed is an incomplete type from its point of declaration to immediately after its enum-base (if any), at which point it becomes a complete type.
An enumeration whose underlying type is not fixed is an incomplete type from its point of declaration to immediately after the closing } of its enum-specifier, at which point it becomes a complete type.
For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration.
If no integral type can represent all the enumerator values, the enumeration is ill-formed.
It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.
If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.
For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type.
Otherwise, for an enumeration where is the smallest enumerator and is the largest, the values of the enumeration are the values in the range to , defined as follows: Let K be 1 for a two's complement representation and 0 for a ones' complement or sign-magnitude representation.
is the smallest value greater than or equal to and equal to , where M is a non-negative integer.
is zero if is non-negative and otherwise.
The size of the smallest bit-field large enough to hold all the values of the enumeration type is if is zero and otherwise.
It is possible to define an enumeration that has values not defined by any of its enumerators.
If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.103
Two enumeration types are layout-compatible enumerations if they have the same underlying type.
The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion.
[Example
:
  enum color { red, yellow, green=20, blue };
  color col = red;
  color* cp = &col;
  if (*cp == blue)              // ...
makes color a type describing various colors, and then declares col as an object of that type, and cp as a pointer to an object of that type.
The possible values of an object of type color are red, yellow, green, blue; these values can be converted to the integral values 0, 1, 20, and 21.
Since enumerations are distinct types, objects of type color can be assigned only values of type color.
color c = 1;                    // error: type mismatch, no conversion from int to color
int i = yellow;                 // OK: yellow converted to integral value 1, integral promotion
Note that this implicit enum to int conversion is not provided for a scoped enumeration:
enum class Col { red, yellow, green };
int x = Col::red;               // error: no Col to int conversion
Col y = Col::red;
if (y) { }                      // error: no Col to bool conversion
end example
]
Each enum-name and each unscoped enumerator is declared in the scope that immediately contains the enum-specifier.
Each scoped enumerator is declared in the scope of the enumeration.
These names obey the scope rules defined for all names in [basic.scope] and [basic.lookup].
[Example
:
enum direction { left='l', right='r' };

void g()  {
  direction d;                  // OK
  d = left;                     // OK
  d = direction::right;         // OK
}

enum class altitude { high='h', low='l' };

void h()  {
  altitude a;                   // OK
  a = high;                     // error: high not in scope
  a = altitude::low;            // OK
}
end example
]
An enumerator declared in class scope can be referred to using the class member access operators (::, . (dot) and -> (arrow)), see [expr.ref].
[Example
:
struct X {
  enum direction { left='l', right='r' };
  int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};

void g(X* p) {
  direction d;                  // error: direction not in scope
  int i;
  i = p->f(left);               // error: left not in scope
  i = p->f(X::right);           // OK
  i = p->f(p->left);            // OK
  // ...
}
end example
]
If an enum-head contains a nested-name-specifier, the enum-specifier shall refer to an enumeration that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set ([namespace.def]) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the enum-specifier shall appear in a namespace enclosing the previous declaration.
In such cases, the nested-name-specifier of the enum-head of the definition shall not begin with a decltype-specifier.
This set of values is used to define promotion and conversion semantics for the enumeration type.
It does not preclude an expression of enumeration type from having a value that falls outside this range.

9.7 Namespaces [basic.namespace]

A namespace is an optionally-named declarative region.
The name of a namespace can be used to access entities declared in that namespace; that is, the members of the namespace.
Unlike other declarative regions, the definition of a namespace can be split over several parts of one or more translation units.
The outermost declarative region of a translation unit is a namespace; see [basic.scope.namespace].

9.7.1 Namespace definition [namespace.def]

namespace-name:
	identifier
	namespace-alias
namespace-definition:
	named-namespace-definition
	unnamed-namespace-definition
	nested-namespace-definition
named-namespace-definition:
	inline namespace attribute-specifier-seq identifier { namespace-body }
unnamed-namespace-definition:
	inline namespace attribute-specifier-seq { namespace-body }
nested-namespace-definition:
	namespace enclosing-namespace-specifier :: identifier { namespace-body }
enclosing-namespace-specifier:
	identifier
	enclosing-namespace-specifier :: identifier
namespace-body:
	declaration-seq
Every namespace-definition shall appear in the global scope or in a namespace scope ([basic.scope.namespace]).
In a named-namespace-definition, the identifier is the name of the namespace.
If the identifier, when looked up, refers to a namespace-name (but not a namespace-alias) that was introduced in the namespace in which the named-namespace-definition appears or that was introduced in a member of the inline namespace set of that namespace, the namespace-definition extends the previously-declared namespace.
Otherwise, the identifier is introduced as a namespace-name into the declarative region in which the named-namespace-definition appears.
Because a namespace-definition contains declarations in its namespace-body and a namespace-definition is itself a declaration, it follows that namespace-definitions can be nested.
[Example
:
namespace Outer {
  int i;
  namespace Inner {
    void f() { i++; }           // Outer​::​i
    int i;
    void g() { i++; }           // Inner​::​i
  }
}
end example
]
The enclosing namespaces of a declaration are those namespaces in which the declaration lexically appears, except for a redeclaration of a namespace member outside its original namespace (e.g., a definition as specified in [namespace.memdef]).
Such a redeclaration has the same enclosing namespaces as the original declaration.
[Example
:
namespace Q {
  namespace V {
    void f();                   // enclosing namespaces are the global namespace, Q, and Q​::​V
    class C { void m(); };
  }
  void V::f() {                 // enclosing namespaces are the global namespace, Q, and Q​::​V
    extern void h();            // ... so this declares Q​::​V​::​h
  }
  void V::C::m() {              // enclosing namespaces are the global namespace, Q, and Q​::​V
  }
}
end example
]
If the optional initial inline keyword appears in a namespace-definition for a particular namespace, that namespace is declared to be an inline namespace.
The inline keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definition that initially declared the namespace-name for that namespace.
The optional attribute-specifier-seq in a named-namespace-definition appertains to the namespace being defined or extended.
Members of an inline namespace can be used in most respects as though they were members of the enclosing namespace.
Specifically, the inline namespace and its enclosing namespace are both added to the set of associated namespaces used in argument-dependent lookup whenever one of them is, and a using-directive that names the inline namespace is implicitly inserted into the enclosing namespace as for an unnamed namespace.
Furthermore, each member of the inline namespace can subsequently be partially specialized, explicitly instantiated, or explicitly specialized as though it were a member of the enclosing namespace.
Finally, looking up a name in the enclosing namespace via explicit qualification ([namespace.qual]) will include members of the inline namespace brought in by the using-directive even if there are declarations of that name in the enclosing namespace.
These properties are transitive: if a namespace N contains an inline namespace M, which in turn contains an inline namespace O, then the members of O can be used as though they were members of M or N.
The inline namespace set of N is the transitive closure of all inline namespaces in N.
The enclosing namespace set of O is the set of namespaces consisting of the innermost non-inline namespace enclosing an inline namespace O, together with any intervening inline namespaces.
A nested-namespace-definition with an enclosing-namespace-specifier E, identifier I and namespace-body B is equivalent to
namespace E { namespace I { B } }
[Example
:
namespace A::B::C {
  int i;
}
The above has the same effect as:
namespace A {
  namespace B {
    namespace C {
      int i;
    }
  }
}
end example
]

9.7.1.1 Unnamed namespaces [namespace.unnamed]

An unnamed-namespace-definition behaves as if it were replaced by
inline namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
where inline appears if and only if it appears in the unnamed-namespace-definition and all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit.
The optional attribute-specifier-seq in the unnamed-namespace-definition appertains to unique.
[Example
:
namespace { int i; }            // unique​::​i
void f() { i++; }               // unique​::​i++

namespace A {
  namespace {
    int i;                      // A​::​unique​::​i
    int j;                      // A​::​unique​::​j
  }
  void g() { i++; }             // A​::​unique​::​i++
}

using namespace A;
void h() {
  i++;                          // error: unique​::​i or A​::​unique​::​i
  A::i++;                       // A​::​unique​::​i
  j++;                          // A​::​unique​::​j
}
end example
]

9.7.1.2 Namespace member definitions [namespace.memdef]

A declaration in a namespace N (excluding declarations in nested scopes) whose declarator-id is an unqualified-id ([dcl.meaning]), whose class-head-name or enum-head-name is an identifier, or whose elaborated-type-specifier is of the form class-key attribute-specifier-seq identifier ([dcl.type.elab]), or that is an opaque-enum-declaration, declares (or redeclares) its unqualified-id or identifier as a member of N.
[Note
:
An explicit instantiation or explicit specialization of a template does not introduce a name and thus may be declared using an unqualified-id in a member of the enclosing namespace set, if the primary template is declared in an inline namespace.
end note
]
[Example
:
namespace X {
  void f() { /* ... */ }        // OK: introduces X​::​f()

  namespace M {
    void g();                   // OK: introduces X​::​M​::​g()
  }
  using M::g;
  void g();                     // error: conflicts with X​::​M​::​g()
}
end example
]
Members of a named namespace can also be defined outside that namespace by explicit qualification ([namespace.qual]) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace.
[Example
:
namespace Q {
  namespace V {
    void f();
  }
  void V::f() { /* ... */ }     // OK
  void V::g() { /* ... */ }     // error: g() is not yet a member of V
  namespace V {
    void g();
  }
}

namespace R {
  void Q::V::g() { /* ... */ }  // error: R doesn't enclose Q
}
end example
]
If a friend declaration in a non-local class first declares a class, function, class template or function template104 the friend is a member of the innermost enclosing namespace.
The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
[Note
:
The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship).
end note
]
If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments ([basic.lookup.argdep]).
If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
[Note
:
The other forms of friend declarations cannot declare a new member of the innermost enclosing namespace and thus follow the usual lookup rules.
end note
]
[Example
:
// Assume f and g have not yet been declared.
void h(int);
template <class T> void f2(T);
namespace A {
  class X {
    friend void f(X);           // A​::​f(X) is a friend
    class Y {
      friend void g();          // A​::​g is a friend
      friend void h(int);       // A​::​h is a friend
                                // ​::​h not considered
      friend void f2<>(int);    // ​::​f2<>(int) is a friend
    };
  };

  // A​::​f, A​::​g and A​::​h are not visible here
  X x;
  void g() { f(x); }            // definition of A​::​g
  void f(X) { /* ... */ }       // definition of A​::​f
  void h(int) { /* ... */ }     // definition of A​::​h
  // A​::​f, A​::​g and A​::​h are visible here and known to be friends
}

using A::x;

void h() {
  A::f(x);
  A::X::f(x);                   // error: f is not a member of A​::​X
  A::X::Y::g();                 // error: g is not a member of A​::​X​::​Y
}
end example
]
this implies that the name of the class or function is unqualified.

9.7.2 Namespace alias [namespace.alias]

The identifier in a namespace-alias-definition is a synonym for the name of the namespace denoted by the qualified-namespace-specifier and becomes a namespace-alias.
[Note
:
When looking up a namespace-name in a namespace-alias-definition, only namespace names are considered, see [basic.lookup.udir].
end note
]
In a declarative region, a namespace-alias-definition can be used to redefine a namespace-alias declared in that declarative region to refer only to the namespace to which it already refers.
[Example
:
The following declarations are well-formed:
namespace Company_with_very_long_name { /* ... */ }
namespace CWVLN = Company_with_very_long_name;
namespace CWVLN = Company_with_very_long_name;  // OK: duplicate
namespace CWVLN = CWVLN;
end example
]

9.7.3 Using directive [namespace.udir]

using-directive:
	attribute-specifier-seq using  namespace nested-name-specifier namespace-name ;
A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope.
[Note
:
When looking up a namespace-name in a using-directive, only namespace names are considered, see [basic.lookup.udir].
end note
]
The optional attribute-specifier-seq appertains to the using-directive.
A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive.
During unqualified name lookup ([basic.lookup.unqual]), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.
[Note
:
In this context, “contains” means “contains directly or indirectly”.
end note
]
A using-directive does not add any members to the declarative region in which it appears.
[Example
:
namespace A {
  int i;
  namespace B {
    namespace C {
      int i;
    }
    using namespace A::B::C;
    void f1() {
      i = 5;        // OK, C​::​i visible in B and hides A​::​i
    }
  }
  namespace D {
    using namespace B;
    using namespace C;
    void f2() {
      i = 5;        // ambiguous, B​::​C​::​i or A​::​i?
    }
  }
  void f3() {
    i = 5;          // uses A​::​i
  }
}
void f4() {
  i = 5;            // ill-formed; neither i is visible
}
end example
]
For unqualified lookup ([basic.lookup.unqual]), the using-directive is transitive: if a scope contains a using-directive that nominates a second namespace that itself contains using-directives, the effect is as if the using-directives from the second namespace also appeared in the first.
[Note
:
For qualified lookup, see [namespace.qual].
end note
]
[Example
:
namespace M {
  int i;
}

namespace N {
  int i;
  using namespace M;
}

void f() {
  using namespace N;
  i = 7;            // error: both M​::​i and N​::​i are visible
}
For another example,
namespace A {
  int i;
}
namespace B {
  int i;
  int j;
  namespace C {
    namespace D {
      using namespace A;
      int j;
      int k;
      int a = i;    // B​::​i hides A​::​i
    }
    using namespace D;
    int k = 89;     // no problem yet
    int l = k;      // ambiguous: C​::​k or D​::​k
    int m = i;      // B​::​i hides A​::​i
    int n = j;      // D​::​j hides B​::​j
  }
}
end example
]
If a namespace is extended ([namespace.def]) after a using-directive for that namespace is given, the additional members of the extended namespace and the members of namespaces nominated by using-directives in the extending namespace-definition can be used after the extending namespace-definition.
[Note
:
If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions or function templates, the use of the name is ill-formed ([basic.lookup]).
In particular, the name of a variable, function or enumerator does not hide the name of a class or enumeration declared in a different namespace.
For example,
namespace A {
  class X { };
  extern "C"   int g();
  extern "C++" int h();
}
namespace B {
  void X(int);
  extern "C"   int g();
  extern "C++" int h(int);
}
using namespace A;
using namespace B;

void f() {
  X(1);             // error: name X found in two namespaces
  g();              // OK: name g refers to the same entity
  h();              // OK: overload resolution selects A​::​h
}
end note
]
During overload resolution, all functions from the transitive search are considered for argument matching.
The set of declarations found by the transitive search is unordered.
[Note
:
In particular, the order in which namespaces were considered and the relationships among the namespaces implied by the using-directives do not cause preference to be given to any of the declarations found by the search.
end note
]
An ambiguity exists if the best match finds two functions with the same signature, even if one is in a namespace reachable through using-directives in the namespace of the other.105
[Example
:
namespace D {
  int d1;
  void f(char);
}
using namespace D;

int d1;             // OK: no conflict with D​::​d1

namespace E {
  int e;
  void f(int);
}

namespace D {       // namespace extension
  int d2;
  using namespace E;
  void f(int);
}

void f() {
  d1++;             // error: ambiguous ​::​d1 or D​::​d1?
  ::d1++;           // OK
  D::d1++;          // OK
  d2++;             // OK: D​::​d2
  e++;              // OK: E​::​e
  f(1);             // error: ambiguous: D​::​f(int) or E​::​f(int)?
  f('a');           // OK: D​::​f(char)
}
end example
]
During name lookup in a class hierarchy, some ambiguities may be resolved by considering whether one member hides the other along some paths ([class.member.lookup]).
There is no such disambiguation when considering the set of names found as a result of following using-directives.

9.8 The using declaration [namespace.udecl]

using-declaration:
	using using-declarator-list ;
using-declarator-list:
	using-declarator ...
	using-declarator-list , using-declarator ...
using-declarator:
	typename nested-name-specifier unqualified-id
Each using-declarator in a using-declaration106 introduces a set of declarations into the declarative region in which the using-declaration appears.
The set of declarations introduced by the using-declarator is found by performing qualified name lookup ([basic.lookup.qual], [class.member.lookup]) for the name in the using-declarator, excluding functions that are hidden as described below.
If the using-declarator does not name a constructor, the unqualified-id is declared in the declarative region in which the using-declaration appears as a synonym for each declaration introduced by the using-declarator.
[Note
:
Only the specified name is so declared; specifying an enumeration name in a using-declaration does not declare its enumerators in the using-declaration's declarative region.
end note
]
If the using-declarator names a constructor, it declares that the class inherits the set of constructor declarations introduced by the using-declarator from the nominated base class.
Every using-declaration is a declaration and a member-declaration and can therefore be used in a class definition.
[Example
:
struct B {
  void f(char);
  void g(char);
  enum E { e };
  union { int x; };
};

struct D : B {
  using B::f;
  void f(int) { f('c'); }       // calls B​::​f(char)
  void g(int) { g('c'); }       // recursively calls D​::​g(int)
};
end example
]
In a using-declaration used as a member-declaration, each using-declarator's nested-name-specifier shall name a base class of the class being defined.
If a using-declarator names a constructor, its nested-name-specifier shall name a direct base class of the class being defined.
[Example
:
template <typename... bases>
struct X : bases... {
  using bases::g...;
};

X<B, D> x;                      // OK: B​::​g and D​::​g introduced
end example
]
[Example
:
class C {
  int g();
};

class D2 : public B {
  using B::f;                   // OK: B is a base of D2
  using B::e;                   // OK: e is an enumerator of base B
  using B::x;                   // OK: x is a union member of base B
  using C::g;                   // error: C isn't a base of D2
};
end example
]
[Note
:
Since destructors do not have names, a using-declaration cannot refer to a destructor for a base class.
Since specializations of member templates for conversion functions are not found by name lookup, they are not considered when a using-declaration specifies a conversion function ([temp.mem]).
end note
]
If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator for the derived class ([class.copy.ctor], [class.copy.assign]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declared copy/move constructor or assignment operator of the derived class, as described below.
A using-declaration shall not name a template-id.
[Example
:
struct A {
  template <class T> void f(T);
  template <class T> struct X { };
};
struct B : A {
  using A::f<double>;           // ill-formed
  using A::X<int>;              // ill-formed
};
end example
]
A using-declaration shall not name a namespace.
A using-declaration shall not name a scoped enumerator.
A using-declaration that names a class member shall be a member-declaration.
[Example
:
struct X {
  int i;
  static int s;
};

void f() {
  using X::i;                   // error: X​::​i is a class member and this is not a member declaration.
  using X::s;                   // error: X​::​s is a class member and this is not a member declaration.
}
end example
]
Members declared by a using-declaration can be referred to by explicit qualification just like other member names ([namespace.qual]).
[Example
:
void f();

namespace A {
  void g();
}

namespace X {
  using ::f;                    // global f
  using A::g;                   // A's g
}

void h()
{
  X::f();                       // calls ​::​f
  X::g();                       // calls A​::​g
}
end example
]
A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed.
[Example
:
namespace A {
  int i;
}

namespace A1 {
  using A::i, A::i;             // OK: double declaration
}

struct B {
  int i;
};

struct X : B {
  using B::i, B::i;             // error: double member declaration
};
end example
]
[Note
:
For a using-declaration whose nested-name-specifier names a namespace, members added to the namespace after the using-declaration are not in the set of introduced declarations, so they are not considered when a use of the name is made.
Thus, additional overloads added after the using-declaration are ignored, but default function arguments ([dcl.fct.default]), default template arguments ([temp.param]), and template specializations ([temp.class.spec], [temp.expl.spec]) are considered.
end note
]
[Example
:
namespace A {
  void f(int);
}

using A::f;         // f is a synonym for A​::​f; that is, for A​::​f(int).
namespace A {
  void f(char);
}

void foo() {
  f('a');           // calls f(int), even though f(char) exists.
}

void bar() {
  using A::f;       // f is a synonym for A​::​f; that is, for A​::​f(int) and A​::​f(char).
  f('a');           // calls f(char)
}
end example
]
[Note
:
Partial specializations of class templates are found by looking up the primary class template and then considering all partial specializations of that template.
If a using-declaration names a class template, partial specializations introduced after the using-declaration are effectively visible because the primary template is visible ([temp.class.spec]).
end note
]
Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region also apply to using-declarations.
[Example
:
namespace A {
  int x;
}

namespace B {
  int i;
  struct g { };
  struct x { };
  void f(int);
  void f(double);
  void g(char);     // OK: hides struct g
}

void func() {
  int i;
  using B::i;       // error: i declared twice
  void f(char);
  using B::f;       // OK: each f is a function
  f(3.5);           // calls B​::​f(double)
  using B::g;
  g('a');           // calls B​::​g(char)
  struct g g1;      // g1 has class type B​::​g
  using B::x;
  using A::x;       // OK: hides struct B​::​x
  x = 99;           // assigns to A​::​x
  struct x x1;      // x1 has class type B​::​x
}
end example
]
If a function declaration in namespace scope or block scope has the same name and the same parameter-type-list as a function introduced by a using-declaration, and the declarations do not declare the same function, the program is ill-formed.
If a function template declaration in namespace scope has the same name, parameter-type-list, return type, and template parameter list as a function template introduced by a using-declaration, the program is ill-formed.
[Note
:
Two using-declarations may introduce functions with the same name and the same parameter-type-list.
If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed.
[Example
:
namespace B {
  void f(int);
  void f(double);
}
namespace C {
  void f(int);
  void f(double);
  void f(char);
}

void h() {
  using B::f;       // B​::​f(int) and B​::​f(double)
  using C::f;       // C​::​f(int), C​::​f(double), and C​::​f(char)
  f('h');           // calls C​::​f(char)
  f(1);             // error: ambiguous: B​::​f(int) or C​::​f(int)?
  void f(int);      // error: f(int) conflicts with C​::​f(int) and B​::​f(int)
}
end example
]
end note
]
When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).
Such hidden or overridden declarations are excluded from the set of declarations introduced by the using-declarator.
[Example
:
struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      // OK: D​::​f(int) overrides B​::​f(int);

  using B::g;
  void g(char);     // OK

  using B::h;
  void h(int);      // OK: D​::​h(int) hides B​::​h(int)
};

void k(D* p)
{
  p->f(1);          // calls D​::​f(int)
  p->f('a');        // calls B​::​f(char)
  p->g(1);          // calls B​::​g(int)
  p->g('a');        // calls D​::​g(char)
}

struct B1 {
  B1(int);
};

struct B2 {
  B2(int);
};

struct D1 : B1, B2 {
  using B1::B1;
  using B2::B2;
};
D1 d1(0);           // ill-formed: ambiguous

struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2(int);          // OK: D2​::​D2(int) hides B1​::​B1(int) and B2​::​B2(int)
};
D2 d2(0);           // calls D2​::​D2(int)
end example
]
[Note
:
For the purpose of forming a set of candidates during overload resolution, the functions that are introduced by a using-declaration into a derived class are treated as though they were members of the derived class ([class.member.lookup]).
In particular, the implicit object parameter is treated as if it were a reference to the derived class rather than to the base class ([over.match.funcs]).
This has no effect on the type of the function, and in all other respects the function remains a member of the base class.
end note
]
Constructors that are introduced by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class ([class.qual]) or forming a set of overload candidates ([over.match.ctor], [over.match.copy], [over.match.list]).
[Note
:
If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class from which the constructor originated are implicitly initialized ([class.inhctor.init]).
A constructor of a derived class is sometimes preferred to a constructor of a base class if they would otherwise be ambiguous ([over.match.best]).
end note
]
In a using-declarator that does not name a constructor, all members of the set of introduced declarations shall be accessible.
In a using-declarator that names a constructor, no access check is performed.
In particular, if a derived class uses a using-declarator to access a member of a base class, the member name shall be accessible.
If the name is that of an overloaded member function, then all functions named shall be accessible.
The base class members mentioned by a using-declarator shall be visible in the scope of at least one of the direct base classes of the class where the using-declarator is specified.
[Note
:
Because a using-declarator designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declarator cannot be used to resolve inherited member ambiguities.
[Example
:
struct A { int x(); };
struct B : A { };
struct C : A {
  using A::x;
  int x(int);
};

struct D : B, C {
  using C::x;
  int x(double);
};
int f(D* d) {
  return d->x();    // error: overload resolution selects A​::​x, but A is an ambiguous base class
}
end example
]
end note
]
A synonym created by a using-declaration has the usual accessibility for a member-declaration.
A using-declarator that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored.
[Example
:
class A {
private:
    void f(char);
public:
    void f(int);
protected:
    void g();
};

class B : public A {
  using A::f;       // error: A​::​f(char) is inaccessible
public:
  using A::g;       // B​::​g is a public synonym for A​::​g
};
end example
]
If a using-declarator uses the keyword typename and specifies a dependent name ([temp.dep]), the name introduced by the using-declaration is treated as a typedef-name.
A using-declaration with more than one using-declarator is equivalent to a corresponding sequence of using-declarations with one using-declarator each.

9.9 The asm declaration [dcl.asm]

An asm declaration has the form
asm-definition:
	attribute-specifier-seq asm ( string-literal ) ;
The asm declaration is conditionally-supported; its meaning is implementation-defined.
The optional attribute-specifier-seq in an asm-definition appertains to the asm declaration.
[Note
:
Typically it is used to pass information through the implementation to an assembler.
end note
]