Inline namespace definitions (C++11)

Note: IBM supports selected features of C++11, known as C++0x before its ratification. IBM will continue to develop and implement the features of this standard. The implementation of the language level is based on IBM's interpretation of the standard. Until IBM's implementation of all the C++11 features is complete, including the support of a new C++11 standard library, the implementation may change from release to release. IBM makes no attempt to maintain compatibility, in source, binary, or listings and other compiler interfaces, with earlier releases of IBM's implementation of the new C++11 features.

Inline namespace definitions are namespace definitions with an initial inline keyword. A namespace so defined is an inline namespace. You can define and specialize members of an inline namespace as if they were also members of the enclosing namespace.

Read syntax diagramSkip visual syntax diagram
Inline namespace definitions syntax

>>-inline--namespace_definition--------------------------------><

When an inline namespace is defined, a using directive is implicitly inserted into its enclosing namespace. While looking up a qualified name through the enclosing namespace, members of the inline namespace are brought in and found by the implicit using directive, even if that name is declared in the enclosing namespace.

For example, if you compile the following code with USE_INLINE_B defined, the output of the resulting executable is 1; otherwise, the output is 2.
namespace A {
#if USE_INLINE_B
   inline
#endif
   namespace B {
      int foo(bool) { return 1; }
   }
   int foo(int) { return 2; }
}

int main(void) {
   return A::foo(true);
}
The properties of inline namespace definitions are transitive; that is, you can use members of an inline namespace as if they were also members of any namespace in its enclosing namespace set, which consists of the innermost non-inline namespace enclosing the inline namespace, together with any intervening inline namespaces. For example:
namespace L {
   inline namespace M {
      inline namespace N {
        / *...* / 
      }
   }
}
In this example, a namespace L contains an inline namespace M, which in turn contains another inline namespace N. The members of N can also be used as if they were members of the namespaces in its enclosing namespace set, i.e., L and M.
Notes:
  • Do not declare the namespace std, which is used for the C++ standard library, as an inline namespace.
  • Do not declare a namespace to be an inline namespace if it is not inline in its first definition.
  • You can declare an unnamed namespace as an inline namespace.

Using inline namespace definitions in explicit instantiation and specialization

You can explicitly instantiate or specialize each member of an inline namespace as if it were a member of its enclosing namespace. Name lookup for the primary template of an explicit instantiation or specialization in a namespace, for example M, considers the inline namespaces whose enclosing namespace set includes M. For example:
namespace L {
   inline namespace M {
       template <typename T> class C; 
   }

   template <typename T> void f(T) { /*...*/ };
}

struct X { /*...*/ };
namespace L {
  template<> class C<X> { /*...*/ };    //template specialization
}

int main()
{
  L::C<X> r;
  f(r);  // fine, L is an associated namespace of C
}
In this example, M is an inline namespace of its enclosing namespace L, class C is a member of inline namespace M, so L is an associated namespace of class C.
The following rules apply when you use inline namespace definitions in explicit instantiation and specialization:
  • An explicit instantiation must be in an enclosing namespace of the primary template if the template name is qualified; otherwise, it must be in the nearest enclosing namespace of the primary template or a namespace in the enclosing namespace set.
  • An explicit specialization declaration must first be declared in the namespace scope of the nearest enclosing namespace of the primary template, or a namespace in the enclosing namespace set. If the declaration is not a definition, it may be defined later in any enclosing namespace.

Using inline namespace definitions in library versioning

With inline namespace definitions, you can provide a common source interface for a library with several implementations, and a user of the library can choose one implementation to be associated with the common interface. The following example demonstrates the use of inline namespace in library versioning with explicit specialization.

//foo.h
#ifndef SOME_LIBRARY_FOO_H_
   #define SOME_LIBRARY_FOO_H_
   namespace SomeLibrary
   {
      #ifdef SOME_LIBRARY_USE_VERSION_2_
         inline namespace version_2 { }
      #else    
      	  inline namespace version_1 { }
      #endif
      namespace version_1 {
       	 template <typename T> int foo(T a) {return 1;}
      }     
      namespace version_2 {
       	 template <typename T> int foo(T a) {return 2;}
      }
   }  
#endif 

//myFooCaller.C 
#include <Foo.h>
#include <iostream>

struct MyIntWrapper { int x;}; 

//Specialize SomeLibrary::foo()
//Should specialize the correct version of foo()

namespace SomeLibrary {
	  template <> int foo(MyIntWrapper a) { return a.x;}
}

int main(void) {
	  using namespace SomeLibrary;
	  MyIntWrapper intWrap = { 4 };
	  std::cout << foo(intWrap) + foo(1.0) << std::endl;
} 
If you compile this example with SOME_LIBRARY_USE_VERSION_2_ defined, the output of the resulting executable is 6; otherwise, the output is 5. If the function call, foo(intWrap), is qualified with one of the inline namespaces, then you need to ensure that the explicit specialization is effective.