10 Declarations [dcl.dcl]

10.1 Specifiers [dcl.spec]

10.1.1 Storage class specifiers [dcl.stc]

The storage class specifiers are

storage-class-specifier:
	static
	thread_local
	extern
	mutable

At most one storage-class-specifier shall appear in a given decl-specifier-seq, except that thread_­local may appear with static or extern. If thread_­local appears in any declaration of a variable it shall be present in all declarations of that entity. If a storage-class-specifier appears in a decl-specifier-seq, there can be no typedef specifier in the same decl-specifier-seq and the init-declarator-list or member-declarator-list of the declaration shall not be empty (except for an anonymous union declared in a named namespace or in the global namespace, which shall be declared static ([class.union.anon])). The storage-class-specifier applies to the name declared by each init-declarator in the list and not to any names declared by other specifiers. A storage-class-specifier other than thread_­local shall not be specified in an explicit specialization or an explicit instantiation directive.

[Note: A variable declared without a storage-class-specifier at block scope or declared as a function parameter has automatic storage duration by default. end note]

The thread_­local specifier indicates that the named entity has thread storage duration. It shall be applied only to the names of variables of namespace or block scope and to the names of static data members. When thread_­local is applied to a variable of block scope the storage-class-specifier static is implied if no other storage-class-specifier appears in the decl-specifier-seq.

The static specifier can be applied only to names of variables and functions and to anonymous unions. There can be no static function declarations within a block, nor any static function parameters. A static specifier used in the declaration of a variable declares the variable to have static storage duration, unless accompanied by the thread_­local specifier, which declares the variable to have thread storage duration. A static specifier can be used in declarations of class members; [class.static] describes its effect. For the linkage of a name declared with a static specifier, see [basic.link].

The extern specifier can be applied only to the names of variables and functions. The extern specifier cannot be used in the declaration of class members or function parameters. For the linkage of a name declared with an extern specifier, see [basic.link]. [Note: The extern keyword can also be used in explicit-instantiations and linkage-specifications, but it is not a storage-class-specifier in such contexts. end note]

The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope, each declaration declaring the same variable name or the same overloading of a function name shall imply the same linkage. Each function in a given set of overloaded functions can have a different linkage, however. [Example:

static char* f();               // f() has internal linkage
char* f()                       // f() still has internal linkage
  { /* ... */ }

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

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

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

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

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

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

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

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

extern int d;                   // d has external linkage
static int d;                   // error: inconsistent linkage

end example]

The name of a declared but undefined class can be used in an extern declaration. Such a declaration can only be used in ways that do not require a complete class type. [Example:

struct S;
extern S a;
extern S f();
extern void g(S);

void h() {
  g(a);                         // error: S is incomplete
  f();                          // error: S is incomplete
}

end example]

The mutable specifier shall appear only in the declaration of a non-static data member whose type is neither const-qualified nor a reference type. [Example:

class X {
  mutable const int* p;         // OK
  mutable int* const q;         // ill-formed
};

end example]

The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const ([dcl.type.cv]).