Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way to express nested namespaces in C++ within the header

People also ask

Should namespaces be in header files?

Code in header files should always use the fully qualified namespace name. The following example shows a namespace declaration and three ways that code outside the namespace can accesses their members.

Should namespaces be indented?

LLVM Coding Standards, https://llvm.org/docs/CodingStandards.html#namespace-indentation: In general, we strive to reduce indentation wherever possible. [...] To facilitate this and avoid some insanely deep nesting on occasion, don't indent namespaces.

Can you nest namespaces?

In C++, namespaces can be nested, and resolution of namespace variables is hierarchical. For example, in the following code, namespace inner is created inside namespace outer, which is inside the global namespace.

Can we have nested namespaces in C sharp?

Namespaces can also be nested in C#. It means we can define namespace inside another namespace. We can access nested namespace using . (Dot) Operator.


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


To avoid really deep indenting, I usually do it this way:

namespace A { namespace B { namespace C
{
    class X
    {
        // ...
    };
}}}

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 #defines.

#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.


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.