related article:
I don’t want to see another “using namespace xxx;” in a header file ever again
-----------
from google c++ style guide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
Definition:Namespaces subdivide the global scope into distinct, named scopes, and so are useful for preventing name collisions in the global scope.
Pros:
Namespaces provide a (hierarchical) axis of naming, in addition to the (also hierarchical) name axis provided by classes.
For example, if two different projects have a class Foo
in the global scope, these symbols may collide at compile time or at runtime. If each project places their code in a namespace, project1::Foo
and project2::Foo
are now distinct symbols that do not collide.
Cons:
Namespaces can be confusing, because they provide an additional (hierarchical) axis of naming, in addition to the (also hierarchical) name axis provided by classes.
Use of unnamed namespaces in header files can easily cause violations of the C++ One Definition Rule (ODR).
Decision:
Use namespaces according to the policy described below. Terminate namespaces with comments as shown in the given examples.
Unnamed Namespaces
- Unnamed namespaces are allowed and even encouraged in
.cc
files, to avoid runtime naming conflicts:namespace { // This is in a .cc file. // The content of a namespace is not indented enum { kUnused, kEOF, kError }; // Commonly used tokens. bool AtEof() { return pos_ == kEOF; } // Uses our namespace's EOF. } // namespace
However, file-scope declarations that are associated with a particular class may be declared in that class as types, static data members or static member functions rather than as members of an unnamed namespace.
- Do not use unnamed namespaces in
.h
files.
Named Namespaces
Named namespaces should be used as follows:
- Namespaces wrap the entire source file after includes, gflags definitions/declarations, and forward declarations of classes from other namespaces:
// In the .h file namespace mynamespace { // All declarations are within the namespace scope. // Notice the lack of indentation. class MyClass { public: ... void Foo(); }; } // namespace mynamespace
// In the .cc file namespace mynamespace { // Definition of functions is within scope of the namespace. void MyClass::Foo() { ... } } // namespace mynamespace
The typical
.cc
file might have more complex detail, including the need to reference classes in other namespaces.#include "a.h" DEFINE_bool(someflag, false, "dummy flag"); class C; // Forward declaration of class C in the global namespace. namespace a { class A; } // Forward declaration of a::A. namespace b { ...code for b... // Code goes against the left margin. } // namespace b
- Do not declare anything in namespace
std
, not even forward declarations of standard library classes. Declaring entities in namespacestd
is undefined behavior, i.e., not portable. To declare entities from the standard library, include the appropriate header file. - You may not use a using-directive to make all names from a namespace available.
// Forbidden -- This pollutes the namespace. using namespace foo;
- You may use a using-declaration anywhere in a
.cc
file, and in functions, methods or classes in.h
files.// OK in .cc files. // Must be in a function, method or class in .h files. using ::foo::bar;
- Namespace aliases are allowed anywhere in a
.cc
file, anywhere inside the named namespace that wraps an entire.h
file, and in functions and methods.// Shorten access to some commonly used names in .cc files. namespace fbz = ::foo::bar::baz; // Shorten access to some commonly used names (in a .h file). namespace librarian { // The following alias is available to all files including // this header (in namespace librarian): // alias names should therefore be chosen consistently // within a project. namespace pd_s = ::pipeline_diagnostics::sidetable; inline void my_inline_function() { // namespace alias local to a function (or method). namespace fbz = ::foo::bar::baz; ... } } // namespace librarian
Note that an alias in a .h file is visible to everyone #including that file, so public headers (those available outside a project) and headers transitively #included by them, should avoid defining aliases, as part of the general goal of keeping public APIs as small as possible.