[basic.scope.scope] (original) (raw)
6 Basics [basic]
6.4.1 General [basic.scope.scope]
The declarations in a program appear in a number of scopesthat 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 scopeat that point.
A scope intervenesbetween 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's target scope is the scope it inhabits.
- Any names (re)introduced by a declaration are bound to it in its target scope.
An entity belongs to a scope Sif 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]).
- 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-list_s_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 correspondif 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 typedef-name) 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,17equivalent ([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(); };struct B { friend void f() {} }; — _end example_]
— _end note_]
[Example 2: typedef int Int;enum E : int { a };void f(int); void f(Int) {} void f(E) {} struct X { static void f();void f() const; void g();void g() const; void g() &; void h(this X&, int);void h(int) &&; void j(this const X&);void j() const &; void k();void k(this X&); }; — _end example_]
A declaration is name-independentif 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 conflictif 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 Bthat 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(); int y; } enum { f }; namespace A {} namespace B = A;namespace B = A; namespace B = B; namespace A = B; namespace B {} void g() { int _; _ = 0; int _; _ = 0; } void h () { int _; _ ++; static int _; } — _end example_]
A declaration is nominablein 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 hare 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.