The thread_local specifier
indicates that the named entity has thread storage duration ([basic.stc.thread]).
It
shall be applied only
to the declaration of a variable of namespace or block scope,
to a structured binding declaration ([dcl.struct.bind]), or
to the declaration of a static data member.
The static specifier shall be applied only
to the declaration of a variable or function,
to a structured binding declaration ([dcl.struct.bind]), or
to the declaration of an anonymous union ([class.union.anon]).
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 ([basic.stc.static]), unless accompanied by the
thread_local specifier, which declares the variable to have thread
storage duration ([basic.stc.thread]).
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 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 2: struct S;
extern S a;
extern S f();
externvoid 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 ([class.mem])
whose type is neither const-qualified nor a reference type.
[Example 3: class X {mutableconstint* p; / OKmutableint*const q; / error};
— 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 ([basic.type.qualifier], [dcl.type.cv]).