158 lines
8.5 KiB
Markdown
158 lines
8.5 KiB
Markdown
[dcl.stc]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.stc)
|
||
|
||
### 9.2.2 Storage class specifiers [dcl.stc]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L518)
|
||
|
||
The storage class specifiers are
|
||
|
||
[storage-class-specifier:](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")
|
||
static
|
||
thread_local
|
||
extern
|
||
mutable
|
||
|
||
At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), except that thread_local may appear with static orextern[.](#1.sentence-2)
|
||
|
||
If thread_local appears in any declaration of
|
||
a variable it shall be present in all declarations of that entity[.](#1.sentence-3)
|
||
|
||
If a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and
|
||
the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") of the declaration shall not be
|
||
empty (except for an anonymous union declared in a namespace scope ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")))[.](#1.sentence-4)
|
||
|
||
The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") in the list and not to any names declared by
|
||
other specifiers[.](#1.sentence-5)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
See [[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation") for restrictions
|
||
in explicit specializations and explicit instantiations, respectively[.](#1.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L546)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
A variable declared without a [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") at block scope or declared as a function parameter
|
||
has [automatic storage duration](basic.stc.auto#def:storage_duration,automatic "6.8.6.4 Automatic storage duration [basic.stc.auto]") by default[.](#2.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L553)
|
||
|
||
The thread_local specifier
|
||
indicates that the named entity has thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#3.sentence-1)
|
||
|
||
It
|
||
shall be applied only
|
||
to the declaration of a variable of namespace or block scope,
|
||
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or
|
||
to the declaration of a static data member[.](#3.sentence-2)
|
||
|
||
When thread_local is applied to a variable of block scope the[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")[.](#3.sentence-3)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L565)
|
||
|
||
The static specifier shall be applied only
|
||
to the declaration of a variable or function,
|
||
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")), or
|
||
to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#4.sentence-1)
|
||
|
||
There can be nostatic function declarations within a block, nor anystatic function parameters[.](#4.sentence-2)
|
||
|
||
A static specifier used in
|
||
the declaration of a variable declares the variable to have static storage
|
||
duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")), unless accompanied by thethread_local specifier, which declares the variable to have thread
|
||
storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"))[.](#4.sentence-3)
|
||
|
||
A static specifier can be
|
||
used in declarations of class members; [[class.static]](class.static "11.4.9 Static members") describes its
|
||
effect[.](#4.sentence-4)
|
||
|
||
For the linkage of a name declared with a static specifier,
|
||
see [[basic.link]](basic.link "6.7 Program and linkage")[.](#4.sentence-5)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L584)
|
||
|
||
The extern specifier shall be applied only to the declaration of a variable
|
||
or function[.](#5.sentence-1)
|
||
|
||
The extern specifier shall not be used in the
|
||
declaration of a class member or function parameter[.](#5.sentence-2)
|
||
|
||
For the linkage of a name declared with an extern specifier,
|
||
see [[basic.link]](basic.link "6.7 Program and linkage")[.](#5.sentence-3)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
The extern keyword can also be used in[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") in such contexts[.](#5.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L600)
|
||
|
||
All declarations for a given entity shall give its name the same linkage[.](#6.sentence-1)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
The linkage given by some declarations is affected by previous declarations[.](#6.sentence-2)
|
||
|
||
Overloads are distinct entities[.](#6.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#example-1)*: static char* f(); // f() has internal linkagechar* f() // f() still has internal linkage{ /* ... */ }char* g(); // g() has external linkagestatic char* g() // error: inconsistent linkage{ /* ... */ }void h();inline void h(); // external linkageinline void l();void l(); // external linkageinline void m();extern void m(); // external linkagestatic void n();inline void n(); // internal linkagestatic int a; // a has internal linkageint a; // error: two definitionsstatic int b; // b has internal linkageextern int b; // b still has internal linkageint c; // c has external linkagestatic int c; // error: inconsistent linkageextern int d; // d has external linkagestatic int d; // error: inconsistent linkage â *end example*]
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L642)
|
||
|
||
The name of a declared but undefined class can be used in anextern declaration[.](#7.sentence-1)
|
||
|
||
Such a declaration can only be used in ways
|
||
that do not require a complete class type[.](#7.sentence-2)
|
||
|
||
[*Example [2](#example-2)*: 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*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L661)
|
||
|
||
The mutable specifier shall appear only in the declaration of
|
||
a non-static data member ([[class.mem]](class.mem "11.4 Class members"))
|
||
whose type is neither const-qualified nor a reference type[.](#8.sentence-1)
|
||
|
||
[*Example [3](#example-3)*: class X {mutable const int* p; // OKmutable int* const q; // error}; â *end example*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L674)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
The mutable specifier on a class data member nullifies aconst specifier applied to the containing class object and
|
||
permits modification of the mutable class member even though the rest of
|
||
the object is const ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers"))[.](#9.sentence-1)
|
||
|
||
â *end note*]
|