13 KiB
[basic.scope.scope]
6 Basics [basic]
6.4 Scope [basic.scope]
6.4.1 General [basic.scope.scope]
The declarations in a program appear in a number of scopes that are in general discontiguous.
The global scope contains the entire program; every other scope S is introduced by a declaration,parameter-declaration-clause,statement,handler, or contract assertion (as described in the following subclauses of [basic.scope]) appearing 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.
Unless otherwise specified:
-
The smallest scope that contains a scope S is the parent scope of S.
-
No two declarations (re)introduce the same entity.
-
A declaration inhabits the immediate scope at its locus ([basic.scope.pdecl]).
-
A declaration's target scope is the scope it inhabits.
-
Any names (re)introduced by a declaration are bound to it in its target scope.
The host scope of a declaration is the inhabited scope if that scope is a block scope and the target scope otherwise.
An entity belongs to a scope S if S is the target scope of a declaration of the entity.
[Note 1:
Special cases include that:
-
Template parameter scopes are parents only to other template parameter scopes ([basic.scope.temp]).
-
Corresponding declarations with appropriate linkage declare the same entity ([basic.link]).
-
The declaration in a template-declaration inhabits the same scope as the template-declaration.
-
Friend declarations and declarations of template specializations do not bind names ([dcl.meaning]); those with qualified names target a specified scope, and other friend declarations and certain elaborated-type-specifiers ([dcl.type.elab]) target a larger enclosing scope.
-
Block-scope extern or function declarations target a larger enclosing scope but bind a name in their immediate scope ([dcl.meaning.general]).
-
The names of unscoped enumerators are bound in the two innermost enclosing scopes ([dcl.enum]).
-
A class's name is also bound in its own scope ([class.pre]).
-
The names of the members of an anonymous union are bound in the union's parent scope ([class.union.anon]).
â end note]
Two non-static member functions havecorresponding object parameters if
exactly one is an implicit object member function with no ref-qualifier and the types of their object parameters ([dcl.fct]), after removing references, are the same, or
their object parameters have the same type.
Two non-static member function templates havecorresponding object parameters if
exactly one is an implicit object member function with no ref-qualifier and the types of their object parameters, after removing any references, are equivalent, or
the types of their object parameters are equivalent.
Two function templates havecorresponding signatures if their template-parameter-lists have the same length, their corresponding template-parameters are equivalent, they have equivalent non-object-parameter-type-lists and return types (if any), and, if both are non-static members, they have corresponding object parameters.
Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
either is a using-declarator, or
one declares a type (not a type alias) and the other declares a variable, non-static data member other than of an anonymous union ([class.union.anon]), enumerator, function, or function template, or
each declares a function or function template and they do not declare corresponding overloads.
Two function or function template declarations declarecorresponding overloads if
both declare functions with the same non-object-parameter-type-list,17 equivalent ([temp.over.link]) trailing requires-clauses (if any, except as specified in [temp.friend]), and, if both are non-static members, they have corresponding object parameters, or
both declare function templates with corresponding signatures and equivalenttemplate-heads and trailing requires-clauses (if any).
[Note 2:
Declarations can correspond even if neither binds a name.
[Example 1: struct A {friend void f(); // #1};struct B {friend void f() {} // corresponds to, and defines, #1}; â end example]
â end note]
[Example 2: typedef int Int;enum E : int { a };void f(int); // #1void f(Int) {} // defines #1void f(E) {} // OK, another overloadstruct X {static void f(); void f() const; // error: redeclarationvoid g(); void g() const; // OKvoid g() &; // error: redeclarationvoid h(this X&, int); void h(int) &&; // OK, another overloadvoid j(this const X&); void j() const &; // error: redeclarationvoid k(); void k(this X&); // error: redeclaration}; â end example]
A declaration is name-independent if its name is _ (U+005f low line) and it declares
a variable with automatic storage duration,
a structured binding with no storage-class-specifier and not inhabiting a namespace scope,
a result binding ([dcl.contract.res]),
the variable introduced by an init-capture, or
a non-static data member of other than an anonymous union.
Recommended practice: Implementations should not emit a warning that a name-independent declaration is used or unused.
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).
The program is ill-formed if, in any scope, a name is bound to two declarations A and B that potentially conflict and A precedes B ([basic.lookup]), unless B is name-independent.
[Note 3:
An id-expression that names a unique name-independent declaration is usable until an additional declaration of the same name is introduced in the same scope ([basic.lookup.general]).
â end note]
[Note 4:
Overload resolution can consider potentially conflicting declarations found in multiple scopes (e.g., via using-directives or for operator functions), in which case it is often ambiguous.
â end note]
[Example 3: void f() {int x,y; void x(); // error: different entity for xint y; // error: redefinition}enum { f }; // error: different entity for ::fnamespace A {}namespace B = A;namespace B = A; // OK, no effectnamespace B = B; // OK, no effectnamespace A = B; // OK, no effectnamespace B {} // error: different entity for Bvoid g() {int _; _ = 0; // OKint _; // OK, name-independent declaration _ = 0; // error: two non-function declarations in the lookup set}void h () {int _; // #1 _ ++; // OKstatic int _; // error: conflicts with #1 because static variables are not name-independent} â end example]
A declaration is nominable in a class, class template, or namespace E at a point P if it precedes P, it does not inhabit a block scope, and its target scope is the scope associated with E or, if E is a namespace, any element of the inline namespace set of E ([namespace.def]).
[Example 4: namespace A {void f() {void g();}inline namespace B {struct S {friend void h(); static int i; }; }}
At the end of this example, the declarations of f, B, S, and h are nominable in A, but those of g and i are not.
â end example]
When instantiating a templated entity ([temp.pre]), any scope S introduced by any part of the template definition is considered to be introduced by the instantiated entity and to contain the instantiations of any declarations that inhabit S.
An implicit object parameter ([over.match.funcs]) is not part of the parameter-type-list.