A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://timsong-cpp.github.io/cppwp/n4659/basic.namespace below:

[basic.namespace]

10.3.1 Namespace definition [namespace.def]
namespace-name:
	identifier
	namespace-alias
namespace-definition:
	named-namespace-definition
	unnamed-namespace-definition
	nested-namespace-definition
named-namespace-definition:
	inlineopt namespace attribute-specifier-seqopt identifier { namespace-body }
unnamed-namespace-definition:
	inlineopt namespace attribute-specifier-seqopt { namespace-body }
nested-namespace-definition:
	namespace enclosing-namespace-specifier :: identifier { namespace-body }
enclosing-namespace-specifier:
	identifier
	enclosing-namespace-specifier :: identifier
namespace-body:
	declaration-seqopt

The enclosing namespaces of a declaration are those namespaces in which the declaration lexically appears, except for a redeclaration of a namespace member outside its original namespace (e.g., a definition as specified in [namespace.memdef]). Such a redeclaration has the same enclosing namespaces as the original declaration. [Example:

namespace Q {
  namespace V {
    void f();                       class C { void m(); };
  }
  void V::f() {                     extern void h();              }
  void V::C::m() {                }
}

end example]

Members of an inline namespace can be used in most respects as though they were members of the enclosing namespace. Specifically, the inline namespace and its enclosing namespace are both added to the set of associated namespaces used in argument-dependent lookup whenever one of them is, and a using-directive that names the inline namespace is implicitly inserted into the enclosing namespace as for an unnamed namespace. Furthermore, each member of the inline namespace can subsequently be partially specialized, explicitly instantiated, or explicitly specialized 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 brought in by the using-directive even if there are declarations of that name in the enclosing namespace.

These properties are transitive: if a namespace N contains an inline namespace M, which in turn contains an inline namespace O, then the members of O 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. The enclosing namespace set of O is the set of namespaces consisting of the innermost non-inline namespace enclosing an inline namespace O, together with any intervening inline namespaces.

10.3.1.1 Unnamed namespaces [namespace.unnamed]

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

inlineopt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

where inline appears if and only if it appears in the unnamed-namespace-definition and all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit. The optional attribute-specifier-seq in the unnamed-namespace-definition appertains to unique. [Example:

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]

10.3.1.2 Namespace member definitions [namespace.memdef]

Members of a named namespace can also be defined outside that namespace by explicit qualification ([namespace.qual]) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace. [Example:

namespace Q {
  namespace V {
    void f();
  }
  void V::f() { /* ... */ }       void V::g() { /* ... */ }       namespace V {
    void g();
  }
}

namespace R {
  void Q::V::g() { /* ... */ }  }

end example]

If a friend declaration in a non-local class first declares a class, function, class template or function template97 the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]). [Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship). end note] If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments ([basic.lookup.argdep]). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. [Note: The other forms of friend declarations cannot declare a new member of the innermost enclosing namespace and thus follow the usual lookup rules. end note] [Example:

void h(int);
template <class T> void f2(T);
namespace A {
  class X {
    friend void f(X);               class Y {
      friend void g();                friend void h(int);                                             friend void f2<>(int);        };
  };

    X x;
  void g() { f(x); }              void f(X) { /* ... */ }         void h(int) { /* ... */ }       }

using A::x;

void h() {
  A::f(x);
  A::X::f(x);                     A::X::Y::g();                 }

end example]

10.3.3 The using declaration [namespace.udecl]
using-declaration:
	using using-declarator-list ;
using-declarator-list:
	using-declarator ...opt
	using-declarator-list , using-declarator ...opt
using-declarator:
	typenameopt nested-name-specifier unqualified-id

Every using-declaration is a declaration and a member-declaration and can therefore be used in a class definition. [Example:

struct B {
  void f(char);
  void g(char);
  enum E { e };
  union { int x; };
};

struct D : B {
  using B::f;
  void f(int) { f('c'); }         void g(int) { g('c'); }       };

end example]

[Note: Since destructors do not have names, a using-declaration cannot refer to a destructor for a base class. Since specializations of member templates for conversion functions are not found by name lookup, they are not considered when a using-declaration specifies a conversion function ([temp.mem]). end note] If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator for the derived class ([class.copy]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declared copy/move constructor or assignment operator of the derived class, as described below.

A using-declaration shall not name a template-id. [Example:

struct A {
  template <class T> void f(T);
  template <class T> struct X { };
};
struct B : A {
  using A::f<double>;             using A::X<int>;              };

end example]

A using-declaration that names a class member shall be a member-declaration. [Example:

struct X {
  int i;
  static int s;
};

void f() {
  using X::i;                     using X::s;                   }

end example]

Members declared by a using-declaration can be referred to by explicit qualification just like other member names ([namespace.qual]). [Example:

void f();

namespace A {
  void g();
}

namespace X {
  using ::f;                      using A::g;                   }

void h()
{
  X::f();                         X::g();                       }

end example]

A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed. [Example:

namespace A {
  int i;
}

namespace A1 {
  using A::i, A::i;             }

struct B {
  int i;
};

struct X : B {
  using B::i, B::i;             };

end example]

[Note: Partial specializations of class templates are found by looking up the primary class template and then considering all partial specializations of that template. If a using-declaration names a class template, partial specializations introduced after the using-declaration are effectively visible because the primary template is visible ([temp.class.spec]). end note]

Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region also apply to using-declarations. [Example:

namespace A {
  int x;
}

namespace B {
  int i;
  struct g { };
  struct x { };
  void f(int);
  void f(double);
  void g(char);     }

void func() {
  int i;
  using B::i;         void f(char);
  using B::f;         f(3.5);             using B::g;
  g('a');             struct g g1;        using B::x;
  using A::x;         x = 99;             struct x x1;      }

end example]

If a function declaration in namespace scope or block scope has the same name and the same parameter-type-list as a function introduced by a using-declaration, and the declarations do not declare the same function, the program is ill-formed. If a function template declaration in namespace scope has the same name, parameter-type-list, return type, and template parameter list as a function template introduced by a using-declaration, the program is ill-formed. [Note: Two using-declarations may introduce functions with the same name and the same parameter-type-list. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed. [Example:

namespace B {
  void f(int);
  void f(double);
}
namespace C {
  void f(int);
  void f(double);
  void f(char);
}

void h() {
  using B::f;         using C::f;         f('h');             f(1);               void f(int);      }

end example] end note]

When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting). Such hidden or overridden declarations are excluded from the set of declarations introduced by the using-declarator. [Example:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      
  using B::g;
  void g(char);     
  using B::h;
  void h(int);      };

void k(D* p)
{
  p->f(1);            p->f('a');          p->g(1);            p->g('a');        }

struct B1 {
  B1(int);
};

struct B2 {
  B2(int);
};

struct D1 : B1, B2 {
  using B1::B1;
  using B2::B2;
};
D1 d1(0);           
struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2(int);          };
D2 d2(0);           

end example]

For the purpose of overload resolution, the functions that are introduced by a using-declaration into a derived class are treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function, and in all other respects the function remains a member of the base class. Likewise, constructors that are introduced by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class ([class.qual]) or forming a set of overload candidates ([over.match.ctor], [over.match.copy], [over.match.list]). If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class from which the constructor originated are implicitly initialized ([class.inhctor.init]).

In a using-declarator that does not name a constructor, all members of the set of introduced declarations shall be accessible. In a using-declarator that names a constructor, no access check is performed. In particular, if a derived class uses a using-declarator to access a member of a base class, the member name shall be accessible. If the name is that of an overloaded member function, then all functions named shall be accessible. The base class members mentioned by a using-declarator shall be visible in the scope of at least one of the direct base classes of the class where the using-declarator is specified.

[Note: Because a using-declarator designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declarator cannot be used to resolve inherited member ambiguities. [Example:

struct A { int x(); };
struct B : A { };
struct C : A {
  using A::x;
  int x(int);
};

struct D : B, C {
  using C::x;
  int x(double);
};
int f(D* d) {
  return d->x();    }

end example] end note]

A synonym created by a using-declaration has the usual accessibility for a member-declaration. A using-declarator that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored. [Example:

class A {
private:
    void f(char);
public:
    void f(int);
protected:
    void g();
};

class B : public A {
  using A::f;       public:
  using A::g;       };

end example]

10.3.4 Using directive [namespace.udir]
using-directive:
	attribute-specifier-seqopt using  namespace nested-name-specifieropt namespace-name ;

A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. 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 nominated namespace. [Note: In this context, “contains” means “contains directly or indirectly”. end note]

A using-directive does not add any members to the declarative region in which it appears. [Example:

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]

For unqualified lookup, the using-directive is transitive: if a scope contains a using-directive that nominates a second namespace that itself contains using-directives, the effect is as if the using-directives from the second namespace also appeared in the first. [Note: For qualified lookup, see [namespace.qual]. end note] [Example:

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]

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, the use of the name is ill-formed. [Note: 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]

During overload resolution, all functions from the transitive search are considered for argument matching. The set of declarations found by the transitive search is unordered. [Note: In particular, the order in which namespaces were considered and the relationships among the namespaces implied by the using-directives do not cause preference to be given to any of the declarations found by the search. end note] An ambiguity exists if the best match finds two functions with the same signature, even if one is in a namespace reachable through using-directives in the namespace of the other.99 [Example:

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]


RetroSearch 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