Is there a better way to express nested namespaces in C++ within the header
Solution 1:
C++17 might simplify nested namespace definition:
namespace A::B::C {
}
is equivalent to
namespace A { namespace B { namespace C {
} } }
See (8) on namespace page on cppreference:
http://en.cppreference.com/w/cpp/language/namespace
Solution 2:
To avoid really deep indenting, I usually do it this way:
namespace A { namespace B { namespace C
{
class X
{
// ...
};
}}}
Solution 3:
I fully support peterchen's answer but want to add something that addresses another part of your question.
Declaring namespaces is one of the very rare cases in C++ where I actually like the use of #define
s.
#define MY_COMPANY_BEGIN namespace MyCompany { // begin of the MyCompany namespace
#define MY_COMPANY_END } // end of the MyCompany namespace
#define MY_LIBRARY_BEGIN namespace MyLibrary { // begin of the MyLibrary namespace
#define MY_LIBRARY_END } // end of the MyLibrary namespace
This also removes the need for comments near the closing brace of the namespace (Did you ever scroll down to the bottom of a large source file and tried to add/remove/balance braces that were missing comments about which brace closes which scope? Not fun.).
MY_COMPANY_BEGIN
MY_LIBRARY_BEGIN
class X { };
class Y { };
MY_LIBRARY_END
MY_COMPANY_END
If you want to put all namespace declarations on a single line you can do that as well with a bit of (pretty ugly) preprocessor magic:
// helper macros for variadic macro overloading
#define VA_HELPER_EXPAND(_X) _X // workaround for Visual Studio
#define VA_COUNT_HELPER(_1, _2, _3, _4, _5, _6, _Count, ...) _Count
#define VA_COUNT(...) VA_HELPER_EXPAND(VA_COUNT_HELPER(__VA_ARGS__, 6, 5, 4, 3, 2, 1))
#define VA_SELECT_CAT(_Name, _Count, ...) VA_HELPER_EXPAND(_Name##_Count(__VA_ARGS__))
#define VA_SELECT_HELPER(_Name, _Count, ...) VA_SELECT_CAT(_Name, _Count, __VA_ARGS__)
#define VA_SELECT(_Name, ...) VA_SELECT_HELPER(_Name, VA_COUNT(__VA_ARGS__), __VA_ARGS__)
// overloads for NAMESPACE_BEGIN
#define NAMESPACE_BEGIN_HELPER1(_Ns1) namespace _Ns1 {
#define NAMESPACE_BEGIN_HELPER2(_Ns1, _Ns2) namespace _Ns1 { NAMESPACE_BEGIN_HELPER1(_Ns2)
#define NAMESPACE_BEGIN_HELPER3(_Ns1, _Ns2, _Ns3) namespace _Ns1 { NAMESPACE_BEGIN_HELPER2(_Ns2, _Ns3)
// overloads for NAMESPACE_END
#define NAMESPACE_END_HELPER1(_Ns1) }
#define NAMESPACE_END_HELPER2(_Ns1, _Ns2) } NAMESPACE_END_HELPER1(_Ns2)
#define NAMESPACE_END_HELPER3(_Ns1, _Ns2, _Ns3) } NAMESPACE_END_HELPER2(_Ns2, _Ns3)
// final macros
#define NAMESPACE_BEGIN(_Namespace, ...) VA_SELECT(NAMESPACE_BEGIN_HELPER, _Namespace, __VA_ARGS__)
#define NAMESPACE_END(_Namespace, ...) VA_SELECT(NAMESPACE_END_HELPER, _Namespace, __VA_ARGS__)
Now you can do this:
NAMESPACE_BEGIN(Foo, Bar, Baz)
class X { };
NAMESPACE_END(Baz, Bar, Foo) // order doesn't matter, NAMESPACE_END(a, b, c) would work equally well
Foo::Bar::Baz::X x;
For nesting deeper than three levels you would have to add helper macros up to the desired count.
Solution 4:
C++ namespaces are used to group interfaces, not to divide components or express political division.
The standard goes out of its way to forbid Java-like use of namespaces. For example, namespace aliases provide a way to easily use deeply-nested or long namespace names.
namespace a {
namespace b {
namespace c {}
}
}
namespace nsc = a::b::c;
But namespace nsc {}
would then be an error, because a namespace may only be defined using its original-namespace-name. Essentially the standard makes things easy for the user of such a library but hard for the implementer. This discourages people from writing such things but mitigates the effects if they do.
You should have one namespace per interface defined by a set of related classes and functions. Internal or optional sub-interfaces might go into nested namespaces. But more than two levels deep should be a very serious red flag.
Consider using underscore characters and identifier prefixes where the ::
operator isn't needed.