Each declaration that appears in a C++ program is only visible in some possibly discontiguous scopes .
Within a scope, unqualified name lookup can be used to associate a name with its declaration.
[edit] GeneralEach program has a global scope , which contains the entire program.
Every other scope S
is introduced by one of the following:
S
always appear in another scope, which thereby contains S
.
An enclosing scope at a program point is any scope that contains it; the smallest such scope is said to be the immediate scope at that point.
A scope intervenes between a program point P
and a scope S
(that does not contain P
) if it is or contains S
but does not contain P
.
The parent scope of any scope S
that is not a template parameter scope is the smallest scope that contains S
and is not a template parameter scope.
Unless otherwise specified:
An entity belongs to a scope S
if S
is the target scope of a declaration of the entity.
// global scope scope // scope S T int x; // ââ // program point X // â { // â ââ { // â â ââ int y; // â â â // program point Y } // â â ââ } // ââ ââ
In the program above:
S
and scope T
contains program point Y
.Y
.S
and T
, and scope S
contains scope T
.T
is the smallest scope among all three, which means:T
is the immediate scope at program point Y
.T
at its locus.T
is the target scope of the declaration of y.T
.S
is the parent scope of scope T
, and the global scope is the parent scope of scope S
.S
intervenes between program point X
and scope T
.Each
introduces a block scope that includes the statement or handler.
A variable that belongs to a block scope is a block 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 scope S
and declares a function or uses the extern specifier, the declaration shall not be attached to a named 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 scope S
.
If a declaration that is not a name-independent declaration and(since C++26) that binds a name in the block scope S
of
potentially conflicts with a declaration whose target scope is the parent scope of S
, the program is ill-formed.
if (int x = f()) // declares âxâ { // the if-block is a substatement of the if-statement int x; // error: redeclaration of âxâ } else { // the else-block is also a substatement of the if-statement int x; // error: redeclaration of âxâ } void g(int i) { extern int i; // error: redeclaration of âiâ }[edit] Function parameter scope
Each parameter declaration P
introduces a function parameter scope that includes P
.
{
body }
.{
requirement-seq }
.int f(int n) // the declaration of the parameter ânâ { // introduces a function parameter scope /* ... */ } // the function parameter scope ends hereLambda scope
Each lambda expression introduces a lambda scope that starts immediately after [
captures ]
and extends to the end of {
body }
.
The captures with initializers of a lambda expression E inhabit the lambda scope introduced by E.
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) [edit] Namespace scope
Every namespace definition for a namespace N
introduces a namespace scope S
that includes the declarations for every namespace definition for N
.
For each non-friend redeclaration or specialization whose target scope is S
or is contained by S
, the following portions are also included in scope S
:
The global scope is the namespace scope of the global namespace.
namespace V // the namespace definition of âVâ { // introduces a namespace scope âSâ // the first part of scope âSâ begins here void 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[edit] Class scope
Each declaration of a class or class template C
introduces a class scope S
that includes the member-specification of the class definition of C
.
For each non-friend redeclaration or specialization whose target scope is S
or is contained by S
, the following portions are also included in scope S
:
class C // the class definition of âCâ { // introduces a class scope âSâ // the first part of scope âSâ begins here void 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[edit] Enumeration scope
Each declaration of an enumeration E
introduces an enumeration scope that includes the enumerator-list of the non-opaque(since C++11) enumeration declaration of E
(if present).
enum class E // the enumeration declaration of âEâ { // introduces an enumeration scope âSâ // scope âSâ begins here e1, e2, e3 // scope âSâ ends here }[edit] Template parameter scope
Each template template parameter introduces a template parameter scope that includes the entire template parameter list and the require clauses(since C++20) of that template template parameter.
Each template declaration D
introduces a template parameter scope S
that extends from the beginning of the template parameter list of D
to the end of D
. Any declaration outside the template parameter list that would inhabit S
instead inhabits the same scope as D
.
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 here template // the template template parameter âTâ // introduces another template parameter scope âS2â < typename T1 typename T2 > requires std::convertible_from<T1, T2> // scope âS2â ends here class 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 scope
Each contract assertion C
introduces a contract-assertion scope that includes C
.
If a postcondition assertion has an identifier which is not name-independent, and the postcondition assertion is associated with a function func potentially conflicts with a declaration D
whose target scope is one of the following scopes, the program is ill-formed:
D
is associated with a lambda expression, the nearest enclosing lambda scope of the precondition assertion.In general, a name is visible after the locus of its first declaration, which is located as follows.
The locus of a name declared in a simple declaration is immediately after that name's declarator 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
const int 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 the template-id that names the template specialization) in its class-head. The class or class template name is already in scope in the list of base classes.
The locus of enum 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 a type 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 a using declaration that does not name a constructor is immediately after the declarator.
template<int N> class Base { protected: static const int next = N + 1; static const int 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).
const int 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 an injected-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 a structured binding declaration is immediately after the identifier-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 the range-declaration of a range-for loop is immediately after the range-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 a template parameter is immediately after its complete template parameter (including the optional default argument).
typedef unsigned char 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 a concept 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 named namespace definition is immediately after the namespace name.
[edit] Defect reportsThe 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 an extern declaration in a block scope couldRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4