| General topics | ||||||||||||||||
| Flow control | ||||||||||||||||
| Conditional execution statements | ||||||||||||||||
| Iteration statements (loops) | ||||||||||||||||
| Jump statements | ||||||||||||||||
| Functions | ||||||||||||||||
| Function declaration | ||||||||||||||||
| Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
| Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
| Exceptions | ||||||||||||||||
| Namespaces | ||||||||||||||||
| Types | ||||||||||||||||
| Specifiers | ||||||||||||||||
| ||||||||||||||||
| Storage duration specifiers | ||||||||||||||||
| Initialization | ||||||||||||||||
| Expressions | ||||||||||||||||
| Alternative representations | ||||||||||||||||
| Literals | ||||||||||||||||
| Boolean -Integer -Floating-point | ||||||||||||||||
| Character -String -nullptr(C++11) | ||||||||||||||||
| User-defined(C++11) | ||||||||||||||||
| Utilities | ||||||||||||||||
| Attributes(C++11) | ||||||||||||||||
| Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
| Type alias declaration(C++11) | ||||||||||||||||
| Casts | ||||||||||||||||
| Memory allocation | ||||||||||||||||
| Classes | ||||||||||||||||
| Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
| Special member functions | ||||||||||||||||
| Templates | ||||||||||||||||
| Miscellaneous | ||||||||||||||||
Eachdeclaration that appears in a C++ program is only visible in some possibly discontiguousscopes .
Within a scope,unqualified name lookup can be used to associate a name with its declaration.
Contents |
Each program has aglobal scope , whichcontains the entire program.
Every other scopeS is introduced by one of the following:
| (since C++26) |
S always appear in another scope, which therebycontainsS.
Anenclosing scope at a program point is any scope that contains it; the smallest such scope is said to be theimmediate scope at that point.
A scopeintervenes between a program pointP and a scopeS (that does not containP) if it is or containsS but does not containP.
Theparent scope of any scopeS that is not atemplate parameter scope is the smallest scope that containsS and is not a template parameter scope.
Unless otherwise specified:
An entitybelongs to a scopeS ifS is the target scope of a declaration of the entity.
// global scope scope// scope S Tint x;// ─┐ // program point X// │{// │ ─┐{// │ │ ─┐int y;// │ │ │ // program point Y}// │ │ ─┘}// ─┘ ─┘
In the program above:
S and scopeT contains program pointY.Y.S andT, and scopeS contains scopeT.T is the smallest scope among all three, which means:T is the immediate scope at program pointY.T at its locus.T is the target scope of the declaration ofy.T.S is the parent scope of scopeT, and the global scope is the parent scope of scopeS.S intervenes between program pointX and scopeT.Each
introduces ablock scope that includes the statement or handler.
A variable that belongs to a block scope is ablock variable (also known as local variable).
int i=42;int a[10]; for(int i=0; i<10; i++)// inner “i” inhabits the block scope a[i]= i;// introduced by the for-statement int j= i;// j = 42
If the declaration inhabits a block scopeS and declares a function or uses theextern specifier, the declaration shall not be attached to anamed module (since C++20), its target scope is a larger enclosing scope (the innermost enclosing namespace scope), but the name is bound in their immediate scopeS.
If a declaration that is not aname-independent declaration and(since C++26) that binds a name in the block scopeS of
| (since C++11) |
potentially conflicts with a declaration whose target scope is the parent scope ofS, the program is ill-formed.
if(int x= f())// declares “x”{// the if-block is a substatement of the if-statementint x;// error: redeclaration of “x”}else{// the else-block is also a substatement of the if-statementint x;// error: redeclaration of “x”} void g(int i){externint i;// error: redeclaration of “i”}
Eachparameter declarationP introduces afunction parameter scope that includesP.
| (since C++11) |
| (since C++17) |
| (since C++20) |
int f(int n)// the declaration of the parameter “n”{// introduces a function parameter scope/* ... */}// the function parameter scope ends here
Lambda scopeEachlambda expression introduces alambda scope that starts immediately after Thecaptures with initializers of a lambda expressionE inhabit the lambda scope introduced byE. auto lambda=[x=1, y]()// this lambda expression introduces a lambda scope,{// it is the target scope of capture “x”/* ... */};// the lambda scope ends before the semicolon | (since C++14) |
Everynamespace definition for a namespaceN introduces anamespace scopeS that includes thedeclarations for every namespace definition forN.
For each non-friend redeclaration or specialization whose target scope isS or is contained byS, the following portions are also included in scopeS:
Theglobal scope is the namespace scope of theglobal namespace.
namespace V// the namespace definition of “V”{// introduces a namespace scope “S”// the first part of scope “S” begins herevoid f();// the first part of scope “S” ends here} void V::f()// the portion after “f” is also a part of scope “S”{void h();// declares V::h}// the second part of scope “S” ends here
Each declaration of a class or class templateC introduces aclass scopeS that includes themember-specification of theclass definition ofC.
For each non-friend redeclaration or specialization whose target scope isS or is contained byS, the following portions are also included in scopeS:
class C// the class definition of “C”{// introduces a class scope “S”// the first part of scope “S” begins herevoid f();// the first part of scope “S” ends here} void C::f()// the portion after “f” is also a part of scope “S”{/* ... */}// the second part of scope “S” ends here
Each declaration of an enumerationE introduces anenumeration scope that includes theenumerator-list of the non-opaque(since C++11)enumeration declaration ofE (if present).
enumclass E// the enumeration declaration of “E”{// introduces an enumeration scope “S”// scope “S” begins here e1, e2, e3// scope “S” ends here}
Eachtemplate template parameter introduces atemplate parameter scope that includes the entire template parameter list and therequire clauses(since C++20) of that template template parameter.
Each template declarationD introduces atemplate parameter scopeS that extends from the beginning of the template parameter list ofD to the end ofD. Any declaration outside the template parameter list that would inhabitS instead inhabits the same scope asD.
Only template parameters belong to a template parameter scope, and only template parameter scopes have a template parameter scope as a parent scope.
// the class template declaration of “X”// introduces a template parameter scope “S1”template<// scope “S1” begins heretemplate// the template template parameter “T”// introduces another template parameter scope “S2”<typename T1typename T2> requires std::convertible_from<T1, T2>// scope “S2” ends hereclass T,typename U>class X;// scope “S1” ends before the semicolon namespace N{template<typename T>using A=struct X;// “X” inhabits the same scope as template// declaration, namely the scope of “N”}
Contract-assertion scopeEachcontract assertion If apostcondition assertion has anidentifier which is notname-independent, and the postcondition assertion is associated with a functionfuncpotentially conflicts with a declaration
| (since C++26) |
In general, a name is visible after thelocus of its first declaration, which is located as follows.
The locus of a name declared in a simple declaration is immediately after that name'sdeclarator and before its initializer, if any.
int x=32;// outer x is in scope {int x= x;// inner x is in scope before the initializer (= x)// this does not initialize inner x with the value of outer x (32),// this initializes inner x with its own (indeterminate) value} std::function<int(int)> f=[&](int n){return n>1? n* f(n-1): n;};// the name of the function f is in scope in the lambda and can// be correctly captured by reference, giving a recursive function
constint x=2;// outer x is in scope {int x[x]={};// inner x is in scope before the initializer (= {}),// but after the declarator (x[x])// in the declarator, outer x is still in scope// this declares an array of 2 int}
The locus of a class or class template declaration is immediately after the identifier that names the class (or thetemplate-id that names the template specialization) in itsclass-head. The class or class template name is already in scope in the list of base classes.
struct S:std::enable_shared_from_this<S>{};// S is in scope at the colon
The locus ofenum specifier or opaque enum declaration(since C++11) is immediately after the identifier that names the enumeration.
enum E:int// E is in scope at the colon{ A= sizeof(E)};
The locus of atype alias or alias template declaration is immediately after the type-id to which the alias refers.
using T=int;// outer T is in scope at the semicolon {using T= T*;// inner T is in scope at the semicolon,// outer T is still in scope before the semicolon// same as T = int*}
The locus for a declarator in ausing declaration that does not name a constructor is immediately after the declarator.
template<int N>class Base{protected:staticconstint next= N+1;staticconstint value= N;}; struct Derived: Base<0>, Base<1>, Base<2>{using Base<0>::next,// next is in scope at the comma Base<next>::value;// Derived::value is 1};
The locus of an enumerator is immediately after its definition (not before the initializer as it is for variables).
constint x=12; {enum{ x= x+1,// enumerator x is in scope at the comma,// outer x is in scope before the comma,// enumerator x is initialized to 13 y= x+1// y is initialized to 14};}
The locus for aninjected-class-name is immediately following the opening brace of its class (or class template) definition.
template<typename T>struct Array// : std::enable_shared_from_this<Array> // error: the injected class name is not in scope:std::enable_shared_from_this< Array<T>>// OK: the template-name Array is in scope{// the injected class name Array is now in scope as if a public member name Array* p;// pointer to Array<T>};
The locus of the implicit declaration for a function-local predefined variable__func__ is immediately before the function body of a function definition. | (since C++11) |
The locus of astructured binding declaration is immediately after theidentifier-list, but structured binding initializers are prohibited from referring to any of the names being declared. | (since C++17) |
The locus of the variable or the structured bindings(since C++17) declared in therange-declaration of arange-for loop is immediately after therange-expression. std::vector<int> x; for(auto x: x)// vector x is in scope before the closing parenthesis,// auto x is in scope at the closing parenthesis{// the auto x is in scope} | (since C++11) |
The locus of atemplate parameter is immediately after its complete template parameter (including the optional default argument).
typedefunsignedchar T; template<class T= T,// template parameter T is in scope at the comma,// typedef name of unsigned char is in scope before the comma T// template parameter T is in scope N=0>struct A{};
The locus of apostcondition assertion with anidentifier is immediately after its | (since C++26) |
The locus of aconcept definition is immediately after the concept name, but concept definitions are prohibited from referring to the concept name being declared. | (since C++20) |
The locus of a namednamespace definition is immediately after the namespace name.
| This section is incomplete Reason: remainder of [basic.scope.pdecl] |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 2793 | C++98 | anextern declaration in a block scope could conflict with another declaration in the parent scope | prohibited |
C documentation forScope |