-1- Declarations specify how names are to be interpreted. Declarations have the form
declaration-seq: declaration declaration-seq declaration
declaration: block-declaration function-definition template-declaration explicit-instantiation explicit-specialization linkage-specification namespace-definition
block-declaration: simple-declaration asm-definition namespace-alias-definition using-declaration using-directive
[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 are described in clause temp. Namespace-definitions are described in namespace.def, using-declarations are described in namespace.udecl and using-directives are described in namespace.udir. ] The simple-declarationsimple-declaration: decl-specifier-seqopt init-declarator-listopt ;
is divided into two parts: decl-specifiers, the components of a decl-specifier-seq, are described in dcl.spec and declarators, the components of an init-declarator-list, are described in clause dcl.decl.decl-specifier-seqopt init-declarator-listopt ;
-2- A declaration occurs in a scope (basic.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 clause 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.
-3- In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (clause class) or enumeration (dcl.enum), 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, and except for the declaration of an unnamed bit-field (class.bit), 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
-4- 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 type-specifiers (dcl.type) 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.
-5- 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.
-6- 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.
-7- Only in function declarations for constructors, destructors, and type conversions can the decl-specifier-seq be omitted.*
[Footnote: The ``implicit int'' rule of C is no longer supported. --- end foonote]
-1- The specifiers that can be used in a declaration are
decl-specifier: storage-class-specifier type-specifier function-specifier friend typedef
decl-specifier-seq: decl-specifier-seqopt decl-specifier
-2- The longest sequence of decl-specifiers that could possibly be a type name is taken as the decl-specifier-seq of a declaration. The sequence shall be self-consistent as described below. [Example:
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,typedef char* Pc; static Pc; //error: name missing
void f(const Pc); //void f(char* const) (not const char*) void g(const int Pc); // void g(const int)
-3- [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)
-1- The storage class specifiers are
At most one storage-class-specifier shall appear in a given decl-specifier-seq. 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 of the declaration shall not be empty (except for global anonymous unions, which shall be declared static (class.union)). 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 shall not be specified in an explicit specialization (temp.expl.spec) or an explicit instantiation (temp.explicit) directive.storage-class-specifier: auto register static extern mutable
-2-
The
auto
or
register
specifiers can be applied only to names of objects declared in
a block (stmt.block)
or to function parameters (dcl.fct.def).
They specify that the named object has automatic storage duration
(basic.stc.auto).
An object declared without a
storage-class-specifier
at block scope or declared as a function parameter has automatic storage duration by
default.
[Note:
hence, the
auto
specifier is almost always redundant and not often used;
one use of
auto
is to distinguish a
declaration-statement
from an
expression-statement
(stmt.ambig) explicitly.
--- end note]
-3-
A
register
specifier has the same semantics as an
auto
specifier together with a hint to the implementation
that the object so declared will be heavily used.
[Note:
the hint can be ignored and in most implementations it will be ignored if the
address of the object is taken.
--- end note]
-4- The static specifier can be applied only to names of objects and functions and to anonymous unions (class.union). There can be no static function declarations within a block, nor any static function parameters. A static specifier used in the declaration of an object declares the object to have static storage duration (basic.stc.static). 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.
-5- The extern specifier can be applied only to the names of objects 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.
-6- A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage.
-7- The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope, each declaration declaring the same object 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
-8- 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 }
class X { mutable const int* p; //OK mutable int* const q; // ill-formed };
-9-
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).
7.1.2 - Function specifiers [dcl.fct.spec]
-1- Function-specifiers can be used only in function declarations.
function-specifier: inline virtual explicit
-2- 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 defined by dcl.fct.spec shall still be respected.
-3- A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration.*
[Footnote: The inline keyword has no effect on the linkage of a function. --- end foonote]
-4- An inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case (basic.def.odr). [Note: a call to the inline function may be encountered before its definition appears in the translation unit. ] If a function 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 with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object. A string literal in an extern inline function is the same object in different translation units.
-5- The virtual specifier shall only be used in declarations of nonstatic class member functions that appear within a member-specification of a class declaration; see class.virtual.
-6-
The
explicit
specifier shall be used only in declarations of constructors within a class
declaration; see class.conv.ctor.
7.1.3 - The typedef specifier [dcl.typedef]
-1- Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental (basic.fundamental) or compound (basic.compound) types. The typedef specifier shall not be used in a function-definition (dcl.fct.def), and it shall not be combined in a decl-specifier-seq with any other kind of specifier except a type-specifier.
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 clause 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: aftertypedef-name: identifier
the constructionstypedef int MILES, *KLICKSP;
are all correct declarations; the type of distance is int; that of metricp is ``pointer to int.'' ]MILES distance; extern KLICKSP metricp;
-2- In a given 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;
-3- 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
typedef int complex; class complex { /* ... */ }; //error: redefinition
-4- A typedef-name that names a class is a class-name (class.name). If a typedef-name is used following the class-key in an elaborated-type-specifier (dcl.type.elab) or in the class-head of a class declaration (class), or is used as the identifier in the declarator for a constructor or destructor declaration (class.ctor, class.dtor), the program is ill-formed. [Example:
struct S { S(); ~S(); }; typedef struct S T; S a = T(); //OK struct T * p; // error
-5- 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). [Example:
typedef struct { } *ps, S; //S is the class name for linkage purposes
typedef struct { S(); //error: requires a return type because S is // an ordinary member function, not a constructor } S;
-1-
The
friend
specifier is used to specify access to class members;
see class.friend.
7.1.5 - Type specifiers [dcl.type]
-1- The type-specifiers are
As a general rule, at most one type-specifier is allowed in the complete decl-specifier-seq of a declaration. The only exceptions to this rule are the following:type-specifier: simple-type-specifier class-specifier enum-specifier elaborated-type-specifier cv-qualifier
-2- At least one type-specifier that is not a cv-qualifier is required in a declaration unless it declares a constructor, destructor or conversion function.*
[Footnote: 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. --- end foonote]
-3-
[Note:
class-specifiers
and
enum-specifiers
are discussed in clause class and dcl.enum, respectively.
The remaining
type-specifiers
are discussed in the rest of this section.
]
7.1.5.1 - The cv-qualifiers [dcl.type.cv]
-1- There are two cv-qualifiers, const and volatile. If a cv-qualifier appears in a decl-specifier-seq, the init-declarator-list of the declaration shall not be empty. [Note: basic.type.qualifier describes how cv-qualifiers affect object and function types. ]
-2- An object declared in namespace scope with a const-qualified type has internal linkage unless it is explicitly declared extern or unless it was previously declared to have external linkage. A variable of const-qualified integral or enumeration type initialized by an integral constant expression can be used in integral constant expressions (expr.const). [Note: 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. ]
-3- 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 (expr.const.cast). ]
-4- Except that any class member declared mutable (dcl.stc) can be modified, any attempt to modify a const object during its lifetime (basic.life) results in undefined behavior.
-5- [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
-6- For another example
class X { public: mutable int i; int j; }; class Y { public: 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 member
-7- If an attempt is made to refer to an object defined with a volatile-qualified type through the use of an lvalue with a non-volatile-qualified type, the program behaviour is undefined.
-8-
[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.
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.
]
7.1.5.2 - Simple type specifiers [dcl.type.simple]
-1- The simple type specifiers are
simple-type-specifier: ::opt nested-name-specifieropt type-name ::opt nested-name-specifier template template-id char wchar_t bool short int long signed unsigned float double void
The simple-type-specifiers specify either a previously-declared user-defined type or one of the fundamental types (basic.fundamental). Table ?? summarizes the valid combinations of simple-type-specifiers and the types they specify.type-name: class-name enum-name typedef-name
Specifier(s) | Type |
type-name | the type named |
char | ``char'' |
unsigned char | ``unsigned char'' |
signed char | ``signed char'' |
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'' |
signed long int | ``long int'' |
signed 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'' |
When multiple
simple-type-specifiers
are allowed, they can be freely intermixed with other
decl-specifiers
in any order.
It is implementation-defined whether bit-fields and objects of
char
type are represented as signed or unsigned quantities.
The
signed
specifier forces
char
objects and bit-fields to be signed; it is redundant with other integral
types.
7.1.5.3 - Elaborated type specifiers [dcl.type.elab]
elaborated-type-specifier: class-key ::opt nested-name-specifieropt identifier enum ::opt nested-name-specifieropt identifier typename ::opt nested-name-specifier identifier typename ::opt nested-name-specifier templateopt template-id
-1- If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization (temp.expl.spec), an explicit instantiation (temp.explicit) or it has one of the following forms:
class-key identifier ; friend class-key identifier ; friend class-key ::identifier ; friend class-key nested-name-specifier identifier ;
-2- 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 a template type-parameter, the elaborated-type-specifier is ill-formed. [Note: this implies that, within a class template with a template type-parameter T, the declaration
is ill-formed. ] If name lookup does not find a declaration for the name, the elaborated-type-specifier is ill-formed unless it is of the simple form class-key identifier in which case the identifier is declared as described in basic.scope.pdecl.friend class T;
-3-
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 (dcl.enum),
the
union
class-key
shall be used to refer to a union (clause class), and
either the
class
or
struct
class-key
shall be used to refer to a class
(clause class) declared using the
class
or
struct
class-key.
7.2 - Enumeration declarations [dcl.enum]
-1- An enumeration is a distinct type (basic.fundamental) with named constants. Its name becomes an enum-name, within its scope.
enum-name: identifier
enum-specifier: enum identifieropt { enumerator-listopt }
enumerator-list: enumerator-definition enumerator-list , enumerator-definition
enumerator-definition: enumerator enumerator = constant-expression
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. The constant-expression shall be of integral or enumeration type. 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.enumerator: identifier
-2- [Example:
defines a, c, and d to be zero, b and e to be 1, and f to be 3. ]enum { a, b, c=0 }; enum { d, e, f=e+2 };
-3- The point of declaration for an enumerator is immediately after its enumerator-definition. [Example:
Here, the enumerator x is initialized with the value of the constant x, namely 12. ]const int x = 12; { enum { x = x }; }
-4- Each enumeration defines a type that is different from all other types. Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. Prior to the closing brace, the type of each enumerator is the type of its initializing value. If an initializer is specified for an enumerator, the initializing value has the same type as the expression. If no initializer is specified for the first enumerator, the type is an unspecified integral type. Otherwise the type is the same as the type of the initializing value 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.
-5- The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration 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. The value of sizeof() applied to an enumeration type, an object of enumeration type, or an enumerator, is the value of sizeof() applied to the underlying type.
-6-
For an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values of the underlying type in the range bmin to bmax, where bmin and bmax are, respectively, the smallest and largest values of the smallest bit-field that can store emin and emax.*
[Footnote: On a two's-complement machine, bmax is the smallest value greater than or equal to max ( abs ( emin ) - 1, abs( emax )) of the form 2M - 1; bmin is zero if emin is non-negative and -( bmax + 1 ) otherwise. --- end foonote]It is possible to define an enumeration that has values not defined by any of its enumerators.
-7- Two enumeration types are layout-compatible if they have the same underlying type.
-8- The value of an enumerator or an object of an enumeration type is converted to an integer by integral promotion (conv.prom). [Example:
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.[ROFF TAB STOPS SET] [ROFF TAB STOPS SET] enum color { red, yellow, green=20, blue }; color col = red; color* cp = &col; if (*cp == blue) //...
color c = 1; //error: type mismatch, // no conversion from int to color
int i = yellow; //OK: yellow converted to integral value 1 // integral promotion
-9- An expression of arithmetic or enumeration type can be converted to an enumeration type explicitly. The value is unchanged if it is in the range of enumeration values of the enumeration type; otherwise the resulting enumeration value is unspecified.
-10- The enum-name and each enumerator declared by an enum-specifier is declared in the scope that immediately contains the enum-specifier. These names obey the scope rules defined for all names in (basic.scope) and (basic.lookup). An enumerator declared in class scope can be referred to using the class member access operators (::, . (dot) and -> (arrow)), see expr.ref. [Example:
class X { public: 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 // ... }
-1- 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.
-2-
A name declared outside all named namespaces, blocks
(stmt.block) and classes (clause class) has global namespace scope
(basic.scope.namespace).
7.3.1 - Namespace definition [namespace.def]
-1- The grammar for a namespace-definition is
namespace-name: original-namespace-name namespace-alias original-namespace-name: identifier namespace-definition: named-namespace-definition unnamed-namespace-definition named-namespace-definition: original-namespace-definition extension-namespace-definition original-namespace-definition: namespace identifier { namespace-body } extension-namespace-definition: namespace original-namespace-name { namespace-body } unnamed-namespace-definition: namespace { namespace-body } namespace-body: declaration-seqopt
-2- The identifier in an original-namespace-definition shall not have been previously defined in the declarative region in which the original-namespace-definition appears. The identifier in an original-namespace-definition is the name of the namespace. Subsequently in that declarative region, it is treated as an original-namespace-name.
-3- The original-namespace-name in an extension-namespace-definition shall have previously been defined in an original-namespace-definition in the same declarative region.
-4- Every namespace-definition shall appear in the global scope or in a namespace scope (basic.scope.namespace).
-5- 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 } }
-1- An unnamed-namespace-definition behaves as if it were replaced by
where all occurrences of unique in a translation unit are replaced by the same identifier and this identifier differs from all other identifiers in the entire program.*namespace unique { /* empty body */ } using namespace unique; namespace unique {namespace-body }
[Footnote: Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit. --- end foonote][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 }
-2-
The use of the
static
keyword is deprecated when declaring objects in a namespace scope
(see annex depr); the
unnamed-namespace
provides a superior
alternative.
7.3.1.2 - Namespace member definitions [namespace.memdef]
-1- Members of a namespace can be defined within that namespace. [Example:
namespace X { void f() { /* ... */ } }
-2- 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 }
-3- Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function*
[Footnote: this implies that the name of the class or function is unqualified. --- end foonote]the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship). If a friend function 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.koenig). When looking for a prior declaration of a class or a function declared as a friend, scopes outside the innermost enclosing namespace scope are not considered. [Example:
//Assume f and g have not yet been defined. void h(int); namespace A { class X { friend void f(X); // A::f 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 }; }; // 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 }
-1- A namespace-alias-definition declares an alternate name for a namespace according to the following grammar:
namespace-alias: identifier namespace-alias-definition: namespace identifier = qualified-namespace-specifier ; qualified-namespace-specifier: ::opt nested-name-specifieropt namespace-name
-2- 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. ]
-3- 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;
-4-
A
namespace-name
or
namespace-alias
shall not be declared as the name of any other entity in the same declarative
region.
A
namespace-name
defined at global scope shall not be declared as the name of any other entity
in any global scope of the program.
No diagnostic is required for a violation of this rule by declarations in
different translation units.
7.3.3 - The using declaration [namespace.udecl]
-1- A using-declaration introduces a name into the declarative region in which the using-declaration appears. That name is a synonym for the name of some entity declared elsewhere.
using-declaration: using typenameopt ::opt nested-name-specifier unqualified-id ; using :: unqualified-id ;
-2- The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears. [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. ]
-3- Every using-declaration is a declaration and a member-declaration and so can 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) };
-4- A using-declaration used as a member-declaration shall refer to a member of a base class of the class being defined, shall refer to a member of an anonymous union that is a member of a base class of the class being defined, or shall refer to an enumerator for an enumeration type that is a member of a base class of the class being defined. [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 };
-5- A using-declaration shall not name a template-id. [Example:
class A { public: template <class T> void f(T); template <class T> struct X { }; }; class B : public A { public: using A::f<double>; //ill-formed using A::X<int>; // ill-formed };
-6- A using-declaration for 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. }
-7- Members declared by a using-declaration can be referred to by explicit qualification just like other member names (namespace.qual). In a using-declaration, a prefix :: refers to the global namespace. [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 }
-8- 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; using A::i; //OK: double declaration } void f() { using A::i; using A::i; // error: double declaration }
class B { public: int i; }; class X : public B { using B::i; using B::i; //error: double member declaration };
-9- The entity declared by a using-declaration shall be known in the context using it according to its definition at the point of the using-declaration. Definitions added to the namespace after the using-declaration are not considered when a use of the name is made. [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) }
-10- Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region (basic.scope) 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 }
-11-
If a function declaration in namespace scope or block scope has the same name
and the same parameter types as a function 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 types.
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) }
-12- When a using-declaration brings names from a base class into a derived class scope, member functions in the derived class override and/or hide member functions with the same name and parameter types in a base class (rather than conflicting). [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) }
-13- For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function, and in all other respects the function remains a member of the base class.
-14- All instances of the name mentioned in a using-declaration shall be accessible. In particular, if a derived class uses a using-declaration 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-declaration shall be visible in the scope of at least one of the direct base classes of the class where the using-declaration is specified. [Note: because a using-declaration designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declaration cannot be used to resolve inherited member ambiguities. For 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(); //ambiguous: B::x or C::x }
-15- The alias created by the using-declaration has the usual accessibility for a member-declaration. [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 };
-16-
[Note:
use of
access-declarations
(class.access.dcl) is deprecated; member
using-declarations
provide a better alternative.
]
7.3.4 - Using directive [namespace.udir]
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. ]using-directive: using namespace ::opt nested-name-specifieropt namespace-name ;
-1-
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''.
]
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 }
-2- 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. [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 }
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 } }
-3- If a namespace is extended by an extended-namespace-definition 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 extended-namespace-definition can be used after the extended-namespace-definition.
-4- 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, the use of the name is ill-formed. [Note: in particular, the name of an object, 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(); } using namespace A; using namespace B;
void f() { X(1); //error: name X found in two namespaces g(); // okay: name g refers to the same entity h(); // error: name h found in two namespaces }
-5- 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. ] 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.*
[Footnote: 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. --- end foonote]
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) }
-1- An asm declaration has the form
The meaning of an asm declaration is implementation-defined. [Note: Typically it is used to pass information through the implementation to an assembler. ]asm-definition: asm ( string-literal ) ;
-1- All function types, function names, and variable names have a language linkage. [Note: Some of the properties associated with an entity with language linkage are specific to each implementation and are not described here. For example, a particular language linkage may be associated with a particular form of representing names of objects and functions with external linkage, or with a particular calling convention, etc. ] The default language linkage of all function types, function names, and variable names is C++ language linkage. Two function types with different language linkages are distinct types even if they are otherwise identical.
-2- Linkage (basic.link) between C++ and non-C++ code fragments can be achieved using a linkage-specification:
The string-literal indicates the required language linkage. The meaning of the string-literal is implementation-defined. A linkage-specification with a string that is unknown to the implementation is ill-formed. When the string-literal in a linkage-specification names a programming language, the spelling of the programming language's name is implementation-defined. [Note: it is recommended that the spelling be taken from the document defining that language, for example Ada (not ADA) and Fortran or FORTRAN (depending on the vintage). The semantics of a language linkage other than C++ or C are implementation-defined. ]linkage-specification: extern string-literal { declaration-seqopt } extern string-literal declaration
-3- Every implementation shall provide for linkage to functions written in the C programming language, "C", and linkage to C++ functions, "C++". [Example:
complex sqrt(complex); //C++ linkage by default extern "C" { double sqrt(double); // C linkage }
-4- Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope (basic.scope). In a linkage-specification, the specified language linkage applies to the function types of all function declarators, function names, and variable names introduced by the declaration(s). [Example:
extern "C" void f1(void(*pf)(int)); //the name f1 and its function type have C language // linkage; pf is a pointer to a C function extern "C" typedef void FUNC(); FUNC f2; // the name f2 has C++ language linkage and the // function's type has C language linkage extern "C" FUNC f3; // the name of function f3 and the function's type // have C language linkage void (*pf2)(FUNC*); // the name of the variable pf2 has C++ linkage and // the type of pf2 is pointer to C++ function that // takes one parameter of type pointer to C function
extern "C" typedef void FUNC_c(); class C { void mf1(FUNC_c*); //the name of the function mf1 and the member // function's type have C++ language linkage; the // parameter has type pointer to C function FUNC_c mf2; // the name of the function mf2 and the member // function's type have C++ language linkage static FUNC_c* q; // the name of the data member q has C++ language // linkage and the data member's type is pointer to // C function };
extern "C" { class X { void mf(); //the name of the function mf and the member // function's type have C++ language linkage void mf2(void(*)()); // the name of the function mf2 has C++ language // linkage; the parameter has type pointer to // C function }; }
-5- If two declarations of the same function or object specify different linkage-specifications (that is, the linkage-specifications of these declarations specify different string-literals), the program is ill-formed if the declarations appear in the same translation unit, and the one definition rule (basic.def.odr) applies if the declarations appear in different translation units. Except for functions with C++ linkage, a function declaration without a linkage specification shall not precede the first linkage specification for that function. A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.
-6- At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. Two declarations for an object with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same object. [Note: because of the one definition rule (basic.def.odr), only one definition for a function or object with C linkage may appear in the program; that is, such a function or object must not be defined in more than one namespace scope. For example,
namespace A { extern "C" int f(); extern "C" int g() { return 1; } extern "C" int h(); }
namespace B { extern "C" int f(); //A::f and B::f refer // to the same function extern "C" int g() { return 1; } // ill-formed, the function g // with C language linkage // has two definitions }
int A::f() { return 98; } //definition for the function f // with C language linkage extern "C" int h() { return 97; } // definition for the function h // with C language linkage // A::h and ::h refer to the same function
-7- Except for functions with internal linkage, a function first declared in a linkage-specification behaves as a function with external linkage. [Example:
is ill-formed (dcl.stc). ] The form of linkage-specification that contains a braced-enclosed declaration-seq does not affect whether the contained declarations are definitions or not (basic.def); the form of linkage-specification directly containing a single declaration is treated as an extern specifier (dcl.stc) for the purpose of determining whether the contained declaration is a definition. [Example:extern "C" double f(); static double f(); //error
extern "C" int i; //declaration extern "C" { int i; // definition }
extern "C" static void f(); //error
-8- [Note: because the language linkage is part of a function type, when a pointer to C function (for example) is dereferenced, the function to which it refers is considered a C function. ]
-9- Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved.