Table of Contents

Overview

Mechanism for expressing logical grouping – various properties of C++ namespaces, including:

Links:

Questions

Terminology

namespace N {                  // [named] namespace definition
  bool f();                    // declaration of f()
  bool f(int);                 // declaration of f(int)
  bool g() { return true; }    // declaration/definition of g()
};

void N::f() { return false; }  // definition

using namespace N;             // using directive
using N::f;                    // using declaration

namespace {                    // unnamed namespace definition
  ...
};

namespace ATT = American_Telephone_and_Telegraph; // namespace alias

Also, namespace identifier is “… either a previously unused identifier, in which case this is original-namespace-definition or the name of a namespace, in which case this is extension-namespace-definition.”

Extensibility (namespaces are "open")

You can extend a namespace by adding names to it from multiple namespace declarations (possibly scattered across multiple header files) – useful for converting older programs to use namespaces:

namespace A {
  int f();
}

namespace A {
  int g();
}

using (declarations and definitions)

Distinction

NOTE: “A using-declaration adds a name to a local scope (also, “introduces a synonym into a scope”). A using-directive does not; it simply renders names accessible in the scope in which they were declared.”

This means that a using declaration will override a using definition; see “Composition and selection.”

using-Declarations

Read this carefully.

“makes the symbol name from the namespace ns_name accessible for unqualified lookup as if declared in the same class scope, block scope, or namespace as where this using-declaration appears.”

using N::f;

NOTE: When used for an overloaded name, a using-declaration applies to all the overloaded versions:

namespace N {
  void f(int);
  void f(string);
};

void g() {
  using N::f;
  f(789);       // N::f(int)
  f("Bruce");   // N::f(string)
}

Useful for introducing base class members into derived class definitions.

using-Directives

cppreference.com link here.

“From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name.”

using namespace N;

Keep their use inside scopes (functions) to avoid massive side effects. Even worse, don't include them in global scopes in header files.

Tradeoffs

Composition and selection

namespace His_lib {
  class String { ... };
  template<typename T>
    class Vector { ... };
  // ...

namespace Her_lib {
  template<typename T>
    class Vector { ... };
  class String { ../ };
  // ...
}

// Does the order of the following matter?

namespace My_lib {
  using namespace His_lib;   // everything from His_lib
  using namespace Her_lib;   // everything from Her_lib

  using His_lib::String;     // resolve potential clash in favor of His_lib
  using Her_lib::Vector;     // resolve potential clash in favor of Her_lib
}

IMPORTANT: When looking into a namespace, names explicitly declared there (including names declared by using-declarations) take priority over names made accessible in another scope by a using-directive (see also §14.4.1). Consequently, a user of My_lib will see the name clashes for String and Vector resolved in favor of His_lib::String and Her_lib::Vector.

Can also rename for clarity:

namespace Lib2 {
  using namespace His_lib; // everything from His_lib
  using namespace Her_lib; // everything from Her_lib

  using His_lib::String; // resolve potential clash in favor of His_lib
  using Her_lib::Vector; // resolve potential clash in favor of Her_lib

  using Her_string = Her_lib::String; // rename
  template<typename T>
    using His_vec = His_lib::Vector<T>; // rename
  ...
}

Nested namespaces

void h();

namespace X {
  void g();
  // ...
  namespace Y {
    void f();
    void ff();
    // ...
  }
}

void X::Y::ff()
{
  f(); g(); h();   // all fine
}

void X::g()
{
  f();             // error: no f() in X
  Y::f();          // OK
}

void h()
{
  f();             // error: no global f()
  Y::f();          // error: no global Y
  X::f();          // error: no f() in X
  X::Y::f();       // OK
}

NOTE: C++17 allows namespace A::B::C { … }.

Namespace aliases

namespace American_Telephone_and_Telegraph { // too long
  // ...
}

American_Telephone_and_Telegraph::String s3 = "Grieg";
American_Telephone_and_Telegraph::String s4 = "Nielsen";

// use namespace alias to shorten names

namespace ATT = American_Telephone_and_Telegraph;

ATT::String s3 = "Grieg";
ATT::String s4 = "Nielsen";

Inline namespaces (new in C++11)

Declarations inside an inline namespace will be visible in its enclosing namespace.

Supports versioning:

namespace Lib
  inline namespace V2_0 {
    ... V2.0 declarations ...
  }
  
  namespace V1_0 {
    ... V1.0 declarations ...
  }
}

Or create your own namespace based on that feature:

// file V99.h:
inline namespace V99 {
	void f(int);	// does something better than the V98 version
	void f(double);	// new feature
	// ...
}

// file V98.h:
namespace V98 {
	void f(int);	// does something
	// ...
}

// file Mine.h:
namespace Mine {
#include "V99.h"
#include "V98.h"
}

We here have a namespace Mine with both the latest release (V99) and the previous one (V98). If you want to be specific, you can:

#include "Mine.h"
using namespace Mine;
// ...
V98::f(1);	// old version
V99::f(1);	// new version
f(1);		// default version (in this case, V99)

One last weird variation, where you can choose your own default:

namespace MyDefault {
  inline
  #include "V3_0.h"      // the new default
  #include "V3_2.h"
  #include "V2_4_2.h"
}

“I do not recommend such intricate use of header files unless it is really necessary. The example above repeatedly violates the rules against including into a nonlocal scope and against having a syntactic construct span file boundaries (the use of inline); see §15.2.2. Sadly, I have seen worse.”

Unnamed namespaces

Its members have potential scope from their point of declaration to the end of the translation unit, and have internal linkage. The aim is to preserve locality of code rather than to present an interface to users.

#include "header.h"
namespace {
  int a;
  void f()  {...}
  int g()   {...}
}

An unnamed namespace has an implied using-directive.

“Unnamed namespaces in different translation units are different. As desired, there is no way of naming a member of an unnamed namespace from another translation unit.”

Argument dependent lookup (ADL)

Coming soon … see here. Particularly useful with:

Basically: