______________________________________________________________________
7 Declarations [dcl.dcl]
______________________________________________________________________
1 A declaration introduces one or more names into a program and speci
fies how those names are to be interpreted. Declarations have the
form
declaration:
decl-specifier-seqopt init-declarator-listopt ;
function-definition
template-declaration
asm-definition
linkage-specification
namespace-definition
namespace-alias-definition
using-declaration
using-directive
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 _temp.dcls_.
Namespace-definitions are described in _namespace.def_, using-
declarations are described in _namespace.udecl_ and using-directives
are described in _namespace.udir_. The description of the general
form of 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 compo
nents of an init-declarator-list, are described in _dcl.decl_.
2 A declaration occurs in a scope (_basic.scope_); the scope rules are
summarized in _class.scope_. 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 this chapter about components in, of, or contained by a declaration
or subcomponent thereof refer only to those components of the declara
tion that are not nested within scopes nested within the declaration.
3 In the general form of declaration, the optional init-declarator-list
can be omitted only when declaring a class (_class_), enumeration
(_dcl.enum_) or namespace (_namespace.def_), that is, when the decl-
specifier-seq contains either a class-specifier, an elaborated-type-
specifier with a class-key (_class.name_), an enum-specifier, or a
namespace-definition. In these cases and whenever a class-specifier,
enum-specifier, or namespace-definition 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,
enumerators, or namespace-name, depending on the syntax).
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 declara
tion is called a typedef declaration and the name of each init-
declarator is declared to be a typedef-name, synonymous with its asso
ciated 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 decla
ration 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-definitions (_dcl.fct.def_) and in function declara
tions for constructors, destructors, and type conversions can the
decl-specifier-seq be omitted.
8 Generally speaking, the names declared by a declaration are introduced
into the scope in which the declaration occurs. The presence of a
friend specifier, certain uses of the elaborated-type-specifier,and
using-directives alter this general behavior, however (see
_class.friend_, _class.name_ and _namespace.udir_)
7.1 Specifiers [dcl.spec]
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. For 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 of
type int called Pc, the type-specifier int shall be present to indi
cate that the typedef-name Pc is the name being (re)declared, rather
than being part of the decl-specifier sequence. For example,
void f(const Pc); // void f(char* const) (not const char*)
void g(const int Pc); // void g(const int)
3 Note that 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. For example,
void h(unsigned Pc); // void h(unsigned int)
void k(unsigned int Pc); // void k(unsigned int)
7.1.1 Storage class specifiers [dcl.stc]
1 The storage class specifiers are
storage-class-specifier:
auto
register
static
extern
mutable
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. 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.
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. 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.expr_) explicitly.
3 A register specifier has the same semantics as an auto specifier
together with a hint to the compiler that the object so declared will
be heavily used. The hint can be ignored and in most implementations
it will be ignored if the address of the object is taken.
4 The static specifier can be applied only to names of objects and func
tions and to anonymous unions (_class.union_). There can be no static
function declarations within a block, nor any static function parame
ters. 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 the declara
tion of class members and its effect is described in _class.static_.
A name declared with a static specifier in a scope other than class
scope (_basic.scope.class_) has internal linkage. For a nonmember
function, an inline specifier is equivalent to a static specifier for
linkage purposes (_basic.link_) unless the inline declaration matches
a previous declaration of the function, in which case the function
name retains the linkage of the previous declaration.
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. A name declared in namespace
scope with the extern specifier has external linkage unless the decla
ration matches a previous declaration, in which case the name retains
the linkage of the previous declaration. An object or function
declared at block scope with the extern specifier has external linkage
unless the declaration matches a visible declaration of namespace
scope that has internal linkage, in which case the object or function
has internal linkage and refers to the same object or function denoted
by the declaration of namespace scope.1)
6 A name declared in a namespace scope without a storage-class-specifier
has external linkage unless it has internal linkage because of a pre
vious declaration and provided it is not declared const. Objects
declared const and not explicitly declared extern have internal link
age.
7 The linkages implied by successive declarations for a given entity
shall agree. That is, within a given scope, each declaration declar
ing the same object name or the same overloading of a function name
shall imply the same linkage. Each function in a given set of over
loaded functions can have a different linkage, however. For 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(); // internal linkage
inline void m();
extern void m(); // internal 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
_________________________
1) Here, ``previously'' includes enclosing scopes. This implies that
a name specified static and then specified extern in an inner scope
still has internal 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, however, cannot be used before the
class has been defined. For example,
struct S;
extern S a;
extern S f();
extern void g(S);
void h()
{
g(a); // error: S undefined
f(); // error: S undefined
}
The mutable specifier can be applied only to names of class data mem
bers (_class.mem_) and can not be applied to names declared const or
static. For example
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 speci
fier 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 The inline specifier is a hint to the compiler that inline substitu
tion of the function body is to be preferred to the usual function
call implementation. The hint can be ignored. The inline specifier
shall not appear on a block scope function declaration. For the link
age of inline functions, see _basic.link_ and _dcl.stc_. A function
(_dcl.fct_, _class.mfct_, _class.friend_) defined within the class
definition is inline by default.
3 An inline function shall be defined in every translation unit in which
it is used (_basic.def.odr_), and shall have exactly the same defini
tion in every case (see one definition rule, _basic.def.odr_). 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. A call to an inline function shall not precede its defini
tion. For example:
class X {
public:
int f();
inline int g();
};
void k(X* p)
{
int i = p->f();
int j = p->g(); // A call appears before X::g is defined
// ill-formed
// ...
}
inline int X::f() // Declares X::f as an inline function
// A call appears before X::f is defined
// ill-formed
{
// ...
}
inline int X::g()
{
// ...
}
4 The virtual specifier shall be used only in declarations of nonstatic
class member functions within a class declaration; see
_class.virtual_.
5 The explicit specifier shall be used only in declarations of construc
tors 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.
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 identi
fier in the way described in _dcl.decl_. If, in a decl-specifier-seq
containing the decl-specifier typedef, there is no type-specifier, or
the only type-specifiers are cv-qualifiers, the typedef declaration is
ill-formed. 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. For example, after
typedef int MILES, *KLICKSP;
the constructions
MILES distance;
extern KLICKSP metricp;
are all correct declarations; the type of distance is int; that of
metricp is pointer to int.
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. For 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. For example,
class complex { /* ... */ };
typedef int complex; // error: redefinition
Similarly, in a given scope, a class 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 itself. For example,
typedef int complex;
class complex { /* ... */ }; // error: redefinition
4 A typedef-name that names a class is a class-name (_class.name_). The
typedef-name shall not be used after a class, struct, or union prefix
and not in the names for constructors and destructors within the class
declaration itself. For example,
struct S {
S();
~S();
};
typedef struct S T;
S a = T(); // ok
struct T * p; // error
5 An unnamed class defined in a declaration with a typedef specifier
gets a dummy name. For linkage purposes only (_basic.link_), the
first typedef-name declared by the declaration is used to denote the
class type in place of the dummy name. For example,
typedef struct { } S, R; // 'S' is the class name for linkage purposes
The typedef-name is still only a synonym for the dummy name and shall
not be used where a true class name is required. Such a class cannot
have explicit constructors or destructors because they cannot be named
by the user. For example,
typedef struct {
S(); // error: requires a return type since S is
// an ordinary member function, not a constructor
} S;
If an unnamed class is defined in a typedef declaration but the decla
ration does not declare a class type, the name of the class for link
age purposes is a dummy name. For example,
typedef struct { }* ps; // 'ps' is not the linkage name of the class
6 A typedef-name that names an enumeration is an enum-name (_dcl.enum_).
The typedef-name shall not be used after an enum prefix.
7.1.4 The friend specifier [dcl.friend]
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
type-specifier:
simple-type-specifier
class-specifier
enum-specifier
elaborated-type-specifier
cv-qualifier
As a general rule, at most one type-specifier is allowed in the com
plete decl-specifier-seq of a declaration. The only exceptions to
this rule are the following:
2
--const or volatile can be combined with any other type-specifier.
However, redundant cv-qualifiers are prohibited except when intro
duced through the use of typedefs (_dcl.typedef_) or template type
arguments (_temp.arg_), in which case the redundant cv-qualifiers
are ignored.
--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.
3 At least one type-specifier is required in a typedef declaration. At
least one type-specifier is required in a function declaration unless
it declares a constructor, destructor or type conversion operator. If
there is no type-specifier or if the only type-specifiers present in a
decl-specifier-seq are cv-qualifiers, then the int specifier is
assumed as default. Regarding the prohibition of the default int
specifier in typedef declarations, see _dcl.typedef_; in all other
instances, the use of decl-specifier-seqs which contain no simple-
type-specifiers (and thus default to plain int) is deprecated.
4 class-specifiers and enum-specifiers are discussed in _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.
_basic.type.qualifier_ describes how cv-qualifiers affect object and
function types.
2 Unless explicitly declared extern, a const object does not have exter
nal linkage and shall be initialized (_dcl.init_; _class.ctor_). An
integral const object initialized by an integral constant expression
can be used in integral constant expressions (_expr.const_).
3 CV-qualifiers are supported by the type system so that they cannot be
subverted without casting (_expr.const.cast_). 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 ref
erenced is a non-const object and can be modified through some other
access path.
4 Except that any class member declare mutable (_dcl.stc_) can be modi
fied, any attempt to modify a const object during its lifetime
(_basic.stc_) 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; // okay: 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 Example
class X {
public:
mutable int i;
int j;
};
class Y { public: X x; }
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 There are no implementation-independent semantics for volatile
objects; volatile is a hint to the compiler to avoid aggressive opti
mization involving the object because the value of the object might be
changed by means undetectable by a compiler.
+------- BEGIN BOX 1 -------+
Notwithstanding the description above, the semantics of volatile are
intended to be the same in C++ as they are in C. However, it's not
possible simply to copy the wording from the C standard until we
understand the ramifications of sequence points, etc.
+------- END BOX 1 -------+
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
char
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
type-name:
class-name
enum-name
typedef-name
The simple-type-specifiers specify either a previously-declared user-
defined type or one of the fundamental types (_basic.fundamental_).
Table 1 summarizes the valid combinations of simple-type-specifiers
and the types they specify.
Table 1--simple-type-specifiers and the types they specify
+-------------------+--------------------+
|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 implementa
tion-defined whether bit-fields and objects of char type are repre
sented 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]
1 Generally speaking, the elaborated-type-specifier is used to refer to
a previously declared class-name or enum-name even though the name can
be hidden by an intervening object, function, or enumerator declara
tion (_basic.scope_), but in some cases it also can be used to declare
a class-name.
elaborated-type-specifier:
class-key ::opt nested-name-specifieropt identifier
enum ::opt nested-name-specifieropt identifier
class-key:
class
struct
union
2 If an elaborated-type-specifier is the sole constituent of a declara
tion, the declaration is ill-formed unless it has one of the following
forms:
-- class-key identifier ;
in which case the elaborated-type-specifier declares the identifier
to be a class-name in the scope that contains the declaration
(_class.name_);
3 -- friend class-key identifier ;
in which case the elaborated-type-specifier declares the identifier
to be a class-name in the smallest enclosing non-class, non-function
prototype scope that contains the declaration;
4 -- friend class-key ::identifier ;
friend class-key nested-name-specifier identifier ;
in which case the identifier is resolved as when the elaborated-
type-specifier is not the sole constituent of a declaration.
5 If the elaborated-type-specifier is not the sole constituent of the
declaration, the identifier following the class-key or enum keyword is
resolved as described in _class.scope_ according to its qualifica
tions, if any, but ignoring any objects, functions, or enumerators
that have been declared. 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, the elaborated-
type-specifier is ill-formed. If the resolution is unsuccessful, the
elaborated-type-specifier is ill-formed unless it is of the simple
form class-key identifier. In this case, the identifier is declared
in the smallest non-class, non-function prototype scope that contains
the declaration.
6 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 (_class_), and either the class or
struct class-key shall be used to refer to a structure (_class_) or to
a class declared using the class class-key. For example:
struct Node {
struct Node* Next; // ok: Refers to Node at global scope
struct Data* Data; // ok: Declares type Data
// at global scope and member Data
};
struct Data {
struct Node* Node; // ok: Refers to Node at global scope
friend struct ::Glob; // error: Glob is not declared
// cannot introduce a qualified type
friend struct Glob; // ok: Declares Glob in global scope
/* ... */
};
struct Base {
struct Data; // ok: Declares nested Data
struct ::Data* thatData; // ok: Refers to ::Data
struct Base::Data* thisData; // ok: Refers to nested Data
friend class ::Data; // ok: global Data is a friend
struct Data { /* ... */ }; // Defines nested Data
struct Data; // ok: Redeclares nested Data
};
struct Data; // ok: Redeclares Data at global scope
struct ::Data; // error: cannot introduce a qualified type
struct Base::Data; // error: cannot introduce a qualified type
struct Base::Datum; // error: Datum undefined
struct Base::Data* pBase; // ok: refers to nested Data
7.2 Enumeration declarations [dcl.enum]
1 An enumeration is a distinct type (_basic.fundamental_) with named
constants. Its name becomes an enum-name, that is, a reserved word
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
enumerator:
identifier
The identifiers in an enumerator-list are declared as constants, and
can appear wherever constants are required. If no enumerator-
definitions with = appear, then the values of the corresponding
constants begin at zero and increase by one as the enumerator-list is
read from left to right. An enumerator-definition with = gives the
associated enumerator the value indicated by the constant-expression;
subsequent enumerators without initializers continue the progression
from the assigned value. The constant-expression shall be of integral
type.
2 For 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.
3 The point of declaration for an enumerator is immediately after its
enumerator-definition. For example:
const int x = 12;
{ enum { x = x }; }
Here, the enumerator x is initialized with the value of the constant
x, namely 12.
4 Each enumeration defines a type that is different from all other
types. The type of an enumerator is its enumeration.
5 The underlying type of an enumeration is an integral type, not gratu
itously larger than int,2) that can represent all enumerator values
defined in the enumeration. 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. On a two's-complement machine,
bmax is the smallest value greater than or equal to
max(abs(emin),abs(emax)) of the form 2M-1; bmin is zero if emin is
non-negative and -(bmax+1) otherwise. 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 sets
of enumerator values.
+------- BEGIN BOX 2 -------+
Shouldn't this be the same underlying type?
+------- END BOX 2 -------+
_________________________
2) The type should be larger than int only if the value of an enumera
tor won't fit in an int.
8 The value of an enumerator or an object of an enumeration type is con
verted to an integer by integral promotion (_conv.prom_). For exam
ple,
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. For example,
color c = 1; // error: type mismatch,
// no conversion from int to color
int i = yellow; // ok: yellow converted to integral value 1
// integral promotion
See also _diff.anac_.
9 An expression of arithmetic type or of type wchar_t 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.
+------- BEGIN BOX 3 -------+
This means the program does not crash.
+------- END BOX 3 -------+
10The 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 (_class.scope_). An enumerator declared in class
scope can be referred to using the class member access operators ( ::,
. (dot) and -> (arrow)), see _expr.ref_. For 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
// ...
}
7.3 Namespaces [basic.namespace]
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 (_class_) has global namespace scope
(_basic.scope.namespace_).
7.3.1 Namespace definition [namespace.def]
1 The grammar for a namespace-definition is
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_).
7.3.1.1 Explict qualification [namespace.qual]
+------- BEGIN BOX 4 -------+
The information in this section is very similar to the information
provided in section _basic.scope.exqual_. The information should prob
ably be consolidated in one place.
+------- END BOX 4 -------+
1 A name in a class or namespace can be accessed using qualification
according to the grammar:
id-expression:
unqualified-id
qualified-id
nested-name-specifier:
class-or-namespace-name :: nested-name-specifieropt
class-or-namespace-name:
class-name
namespace-name
namespace-name:
original-namespace-name
namespace-alias
2 The namespace-names in a nested-name-specifier shall have been previ
ously defined by a named-namespace-definition or a namespace-alias-
definition.
3 The search for the initial qualifier preceding any :: operator locates
only the names of types or namespaces. The search for a name after a
:: locates only names members of a namespace or class. In particular,
using-directives (_namespace.udir_) are ignored, as is any enclosing
declarative region.
7.3.1.2 Unnamed namespaces [namespace.unnamed]
1 An unnamed-namespace-definition behaves as if it were replaced by
namespace unique { namespace-body }
using namespace unique;
where, for each translation unit, all occurrences of unique in that
translation unit are replaced by an identifier that differs from all
other identifiers in the entire program.3) For example:
_________________________
3) Although entities in an unnamed namespace might have external link
age, they are effectively qualified by a name unique to their transla
tion unit and therefore can never be seen from any other translation
unit.
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++; // error: A::i undefined
j++; // A::unique::j
}
7.3.1.3 Namespace scope [namespace.scope]
1 The declarative region of a namespace-definition is its namespace-
body. The potential scope denoted by an original-namespace-name is
the concatenation of the declarative regions established by each of
the namespace-definitions in the same declarative region with that
original-namespace-name. Entities declared in a namespace-body are
said to be members of the namespace, and names introduced by these
declarations into the declarative region of the namespace are said to
be member names of the namespace. For example
namespace N {
int i;
int g(int a) { return a; }
void k();
void q();
}
namespace { int k=1; }
namespace N {
int g(char a) // overloads N::g(int)
{
return k+a; // k is from unnamed namespace
}
int i; // error: duplicate definition
void k(); // ok: duplicate function declaration
void k() // ok: definition of N::k()
{
return g(a); // calls N::g(int)
}
int q(); // error: different return type
}
2 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. For example:
namespace Outer {
int i;
namespace Inner {
void f() { i++; } // Outer::i
int i;
void g() { i++; } // Inner::i
}
}
3 The use of the static keyword is deprecated when declaring objects in
a namespace scope (see _future.directions_); the unnamed-namespace
provides a superior alternative.
7.3.1.4 Namespace member definitions [namespace.memdef]
1 Members of a namespace can be defined within that namespace. For
example:
namespace X {
void f() { /* ... */ }
}
2 Members of a named namespace can also be defined outside that names
pace 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 decla
ration in a namespace that encloses the declaration's namespace. For
example:
namespace Q {
namespace V {
void f();
}
void V::f() { /* ... */ } // fine
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 names
pace. A friend function first declared within a class is a member of
the innermost enclosing namespace. For example:
// Assume f and g have not yet been defined.
namespace A {
class X {
friend void f(X); // declaration of f
class Y {
friend void g();
};
};
void f(X) { /* ... */} // definition of f declared above
X x;
void g() { f(x); } // f and g are members of A
}
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
}
The scope of class names first introduced in elaborated-type-
specifiers is described in (_dcl.type.elab_).
4 When an entity declared with the extern specifier is not found to
refer to some other declaration, then that entity is a member of the
innermost enclosing namespace. However such a declaration does not
introduce the member name in its namespace scope. For example:
namespace X {
void p()
{
q(); // error: q not yet declared
extern void q(); // q is a member of namespace X
}
void middle()
{
q(); // error: q not yet declared
}
void q() { /* ... */ } // definition of X::q
}
void q() { /* ... */ } // some other, unrelated q
7.3.2 Namespace or class alias [namespace.alias]
1 A namespace-alias-definition declares an alternate name for a names
pace according to the following grammar:
namespace-alias:
identifier
namespace-alias-definition:
namespace identifier = qualified-namespace-specifier ;
qualified-namespace-specifier:
::opt nested-name-specifieropt class-or-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.
3 In a declarative region, a namespace-alias-definition can be used to
redefine a namespace-alias declared in that declarative region to
refer to the namespace to which it already refers. For 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 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 viola
tion 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 ::opt nested-name-specifier unqualified-id ;
using :: unqualified-id ;
+------- BEGIN BOX 5 -------+
There is still an open issue regarding the "opt" on the nested-name-
specifier.
+------- END BOX 5 -------+
2 The member names specified in a using-declaration are declared in the
declarative region in which the using-declaration appears.
3 Every using-declaration is a declaration and a member-declaration and
so can be used in a class definition. For example:
struct B {
void f(char);
void g(char);
};
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 mem
ber of a base class of the class being defined. For example:
class C {
int g();
};
class D2 : public B {
using B::f; // ok: B is a base of D
using C::g; // error: C isn't a base of D2
};
5 A using-declaration for a member shall be a member-declaration. For
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.
}
6 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 (as
ever). For 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
}
7 A using-declaration is a declaration and can therefore be used repeat
edly where (and only where) multiple declarations are allowed. For
example:
namespace A {
int i;
}
void f()
{
using A::i;
using A::i; // ok: double declaration
}
class B {
int i;
};
class X : public B {
using B::i;
using B::i; // error: double member declaration
};
8 The entity declared by an using-declaration shall be known in the con
text 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. For
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)
}
9 A name defined by a using-declaration is an alias for its original
declarations so that the using-declaration does not affect the type,
linkage or other attributes of the members referred to.
10If the set of local declarations and using-declarations for a single
name are given in a declarative region, they shall all refer to the
same entity, or all refer to functions. For example
namespace B {
int i;
void f(int);
void f(double);
}
void g()
{
int i;
using B::i; // error: i declared twice
void f(char);
using B::f; // fine: each f is a function
}
11If a local function declaration has the same name and type as a func
tion introduced by a using-declaration, the program is ill-formed.
For example:
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)
}
12When a using-declaration brings names from a base class into a derived
class scope, member functions in the derived class override virtual
member functions with the same name and argument types in a base class
(rather than conflicting). For 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); // error: D::h(int) conflicts with 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)
}
+------- BEGIN BOX 6 -------+
For p->g(1) to be unambiguous, the D::g(int) synonym for B::g(int)
must take part in the overload resolution as if it was a member of D,
though its type must be ``member of B.'' A proper phrasing for this
is being prepared for a vote.
+------- END BOX 6 -------+
13All 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.
14The alias created by the using-declaration has the usual accessibility
for a member-declaration. For 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
};
15Use of access-declarations (_class.access.dcl_) is deprecated; member
using-declarations provide a better alternative.
7.3.4 Using directive [namespace.udir]
1 using-directive:
using namespace ::opt nested-name-specifieropt namespace-name ;
2 A using-directive specifies that the names in the namespace with the
given namespace-name, including those specified by any using-
directives in that namespace, can be used in the scope in which the
using-directive appears after the using directive, exactly as if the
names from the namespace had been declared outside a namespace at the
points where the namespace was defined. A using-directive does not
add any members to the declarative region in which it appears. If a
namespace is extended by an extended-namespace-definition after a
using-directive is given, the additional members of the extended
namespace can be used after the extended-namespace-definition.
3 The using-directive is transitive: if a namespace 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. In particular, a name in
a namespace does not hide names in a second namespace which is the
subject of a using-directive in the first namespace. For example:
namespace M {
int i;
}
namespace N {
int i;
using namespace M;
}
void f()
{
N::i = 7; // well-formed: M::i is not a member of N
using namespace N;
i = 7; // error: both M::i and N::i are accessible
}
4 During overload resolution, all functions from the transitive search
are considered for argument matching. An ambiguity exists if the best
match finds two functions with the same signature, even if one might
seem to ``hide'' the other in the using-directive lattice. For exam
ple:
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)
}
7.4 The asm declaration [dcl.asm]
1 An asm declaration has the form
asm-definition:
asm ( string-literal ) ;
The meaning of an asm declaration is implementation dependent. Typi
cally it is used to pass information through the compiler to an assem
bler.
7.5 Linkage specifications [dcl.link]
1 Linkage (_basic.link_) between C++ and non-C++ code fragments can be
achieved using a linkage-specification:
linkage-specification:
extern string-literal { declaration-seqopt }
extern string-literal declaration
declaration-seq:
declaration
declaration-seq declaration
The string-literal indicates the required linkage. The meaning of the
string-literal is implementation dependent. Every implementation
shall provide for linkage to functions written in the C programming
language, "C", and linkage to C++ functions, "C++". Default linkage
is "C++". For example,
complex sqrt(complex); // C++ linkage by default
extern "C" {
double sqrt(double); // C linkage
}
+------- BEGIN BOX 7 -------+
This example might need to be revisited depending on what the rules
ultimately are concerning C++ linkage to standard library functions
from the C library.
+------- END BOX 7 -------+
2 Linkage specifications nest. A linkage specification does not estab
lish a scope. A linkage-specification can occur only in namespace
scope (_basic.scope_). A linkage-specification for a class applies to
nonmember functions and objects declared within it. A linkage-
specification for a function also applies to functions and objects
declared within it. A linkage declaration with a string that is
unknown to the implementation is ill-formed.
3 If a function has more than one linkage-specification, they shall
agree; that is, they shall specify the same string-literal. Except
for functions with C++ linkage, a function declaration without a link
age specification shall not precede the first linkage specification
for that function. A function can be declared without a linkage spec
ification after an explicit linkage specification has been seen; the
linkage explicitly specified in the earlier declaration is not
affected by such a function declaration.
4 At most one of a set of overloaded functions (_over_) with a particu
lar name can have C linkage.
5 Linkage can be specified for objects. For example,
extern "C" {
// ...
_iobuf _iob[_NFILE];
// ...
int _flsbuf(unsigned,_iobuf*);
// ...
}
Functions and objects can be declared static or inline within the {}
of a linkage specification. The linkage directive is ignored for a
function or object with internal linkage (_basic.link_). A function
first declared in a linkage specification behaves as a function with
external linkage. For example,
extern "C" double f();
static double f(); // error
is ill-formed (_dcl.stc_). An object defined within an
extern "C" { /* ... */ }
construct is still defined (and not just declared).
6 Linkage from C++ to objects defined in other languages and to objects
defined in C++ from other languages is implementation and language
dependent. Only where the object layout strategies of two language
implementations are similar enough can such linkage be achieved. Tak
ing the address of a function whose linkage is other than C++ or C
produces undefined behavior.
7 When the name of a programming language is used to name a style of
linkage in the string-literal in a linkage-specification, it is recom
mended that the spelling be taken from the document defining that lan
guage, for example, Ada (not ADA) and FORTRAN (not Fortran).