[basic.namespace] (original) (raw)

9 Declarations [dcl]

9.9 Namespaces [basic.namespace]


9.9.1 General [basic.namespace.general]

9.9.2 Namespace definition [namespace.def]

9.9.2.1 General [namespace.def.general]

9.9.2.2 Unnamed namespaces [namespace.unnamed]

9.9.3 Namespace alias [namespace.alias]

9.9.4 Using namespace directive [namespace.udir]


9.9.1 General [basic.namespace.general]

A namespace is an optionally-named entity whose scope can contain declarations of any kind of entity.

The name of a namespace can be used to access entities that belong to that namespace; that is, the members of the namespace.

Unlike other entities, the definition of a namespace can be split over several parts of one or more translation units and modules.

[Note 1:

A namespace is never attached to a named module and never has a name with module linkage.

— _end note_]

[Example 1: export module M;namespace N1 {} export namespace N2 {} namespace N3 { export int n; } — _end example_]

The global namespace belongs to the global scope; it is not an unnamed namespace ([namespace.unnamed]).

[Note 2:

Lacking a declaration, it cannot be found by name lookup.

— _end note_]

9.9.2 Namespace definition [namespace.def]

9.9.2.1 General [namespace.def.general]

In a named-namespace-definition D, the identifier is the name of the namespace.

The identifier is looked up by searching for it in the scopes of the namespace Ain which D appears and of every element of the inline namespace set of A.

If the lookup finds a namespace-definition for a namespace N,D extends N, and the target scope of D is the scope to which N belongs.

If the lookup finds nothing, the identifier is introduced as a namespace-name into A.

Because a namespace-definition containsdeclarations in its namespace-body and anamespace-definition is itself a declaration, it follows that namespace-definitions can be nested.

[Example 1: namespace Outer { int i;namespace Inner { void f() { i++; } int i;void g() { i++; } } } — _end example_]

If the optional initial inline keyword appears in anamespace-definition for a particular namespace, that namespace is declared to be an inline namespace.

The inline keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definitionthat initially declared the namespace-name for that namespace.

Members of an inline namespace can be used in most respects as though they were members of the innermost enclosing namespace.

Specifically, the inline namespace and its enclosing namespace are both added to the set of associated namespaces used inargument-dependent lookup whenever one of them is, and a using-directive ([namespace.udir]) that names the inline namespace is implicitly inserted into the enclosing namespace as for an unnamed namespace ([namespace.unnamed]).

Furthermore, each member of the inline namespace can subsequently be partially specialized ([temp.spec.partial]), explicitly instantiated ([temp.explicit]), or explicitly specialized ([temp.expl.spec]) as though it were a member of the enclosing namespace.

Finally, looking up a name in the enclosing namespace via explicit qualification ([namespace.qual]) will include members of the inline namespace even if there are declarations of that name in the enclosing namespace.

These properties are transitive: if a namespace N contains an inline namespaceM, which in turn contains an inline namespace O, then the members ofO can be used as though they were members of M or N.

The inline namespace set of N is the transitive closure of all inline namespaces in N.

A nested-namespace-definition with anenclosing-namespace-specifier E,identifier I andnamespace-body Bis equivalent tonamespace E { inline namespace I { B } } where the optional inline is present if and only if the identifier I is preceded by inline.

[Example 2: namespace A::inline B::C { int i;}

The above has the same effect as:namespace A { inline namespace B { namespace C { int i;} } }

— _end example_]

9.9.2.2 Unnamed namespaces [namespace.unnamed]

An unnamed-namespace-definition behaves as if it were replaced by

inline namespace unique { }
using namespace unique ;
namespace unique { namespace-body }

whereinline appears if and only if it appears in theunnamed-namespace-definitionand all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the program.

[Example 1: namespace { int i; } void f() { i++; } namespace A { namespace { int i; int j; } void g() { i++; } } using namespace A;void h() { i++; A::i++; j++; } — _end example_]

9.9.3 Namespace alias [namespace.alias]

A namespace-alias-definition declares a namespace aliasaccording to the following grammar:

The splice-specifier (if any) shall designate a namespace that is not the global namespace.

9.9.4 Using namespace directive [namespace.udir]

The splice-specifier (if any) shall designate a namespace that is not the global namespace.

A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope.

[Note 2:

During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the designated namespace.

— _end note_]

[Note 3:

A using-directive does not introduce any names.

— _end note_]

[Example 1: namespace A { int i;namespace B { namespace C { int i;} using namespace A::B::C;void f1() { i = 5; } } namespace D { using namespace B;using namespace C;void f2() { i = 5; } } void f3() { i = 5; } } void f4() { i = 5; } — _end example_]

[Note 4:

A using-directive is transitive: if a scope contains ausing-directive that designates a namespace that itself contains using-directives, the namespaces designated by thoseusing-directives are also eligible to be considered.

— _end note_]

[Example 2: namespace M { int i;} namespace N { int i;using namespace M;} void f() { using namespace N; i = 7; }

For another example,namespace A { int i;} namespace B { int i;int j;namespace C { namespace D { using namespace A;int j;int k;int a = i; } using namespace D;int k = 89; int l = k; int m = i; int n = j; } }

— _end example_]

[Note 5:

Declarations in a namespace that appear after a using-directive for that namespace can be found through that using-directive after they appear.

— _end note_]

[Note 6:

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions or function templates, the use of the name is ill-formed ([basic.lookup]).

In particular, the name of a variable, function or enumerator does not hide the name of a class or enumeration declared in a different namespace.

For example,namespace A { class X { };extern "C" int g();extern "C++" int h();} namespace B { void X(int);extern "C" int g();extern "C++" int h(int);} using namespace A;using namespace B;void f() { X(1); g(); h(); }

— _end note_]

[Note 7:

The order in which namespaces are considered and the relationships among the namespaces implied by theusing-directives do not affect overload resolution.

Neither is any function excluded because another has the same signature, even if one is in a namespace reachable throughusing-directives in the namespace of the other.83

— _end note_]

[Example 3: namespace D { int d1;void f(char);} using namespace D;int d1; namespace E { int e;void f(int);} namespace D { int d2;using namespace E;void f(int);} void f() { d1++; ::d1++; D::d1++; d2++; e++; f(1); f('a'); } — _end example_]