Inline namespace definitions (C++11)
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.
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.
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);
}
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.- 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
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. - 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.