Warning: include_once(/var/www/web/../var/bootstrap.php.cache): failed to open stream: No such file or directory in /var/www/web/app.php on line 11

Warning: include_once(): Failed opening '/var/www/web/../var/bootstrap.php.cache' for inclusion (include_path='.:') in /var/www/web/app.php on line 11

Warning: session_cache_limiter(): Cannot change cache limiter when headers already sent in /var/www/var/cache/prod/classes.php on line 91

Warning: ini_set(): Headers already sent. You cannot change the session module's ini settings at this time in /var/www/var/cache/prod/classes.php on line 91

Warning: ini_set(): Headers already sent. You cannot change the session module's ini settings at this time in /var/www/var/cache/prod/classes.php on line 203

Warning: ini_set(): Headers already sent. You cannot change the session module's ini settings at this time in /var/www/var/cache/prod/classes.php on line 203

Warning: session_set_save_handler(): Cannot change save handler when headers already sent in /var/www/var/cache/prod/classes.php on line 222
Rogiel.com — Blog — The benefits of nested namespaces in C++

C++ nested namespaces, contrary to popular belief, are NOT evil.

Good news everyone! UPDATE

A proposal has been submitted to C++17 (or C++1z) for a better nested namespaces declaration! Read more

I was browsing over StackOverflow and found a great question regarding nested namespaces in C++. I have always been a huge user of nested namespaces, I had projects that grew to more than 5 nested namespaces.

What really called my attention was Jimmy J answer in which he says:

You're over-using them (and you'll get nothing in return).

Sorry, what? Nothing in return? Really? Well, I don't think this is even close to the truth.

Namespaces can be a documentation tool

Let's say you want to do some queries on the database. You could just type MyProject::Database:: and code completion would already give you sugestions like:

  • MyProject::Database::DatabaseService
  • MyProject::Database::Query
  • MyProject::Database::ResultSet

Now, you know exactly what classes belong to the database domain and you know all of them.

Alternatively, you could prefix classes with a "Database" tag, like:

  • MyProject::DatabaseService
  • MyProject::DatabaseQuery
  • MyProject::DatabaseResultSet

It is okay to do that (and I, myself, do that sometimes), but there are issues with this. Your class names become larger (namespaces makes only their qualifiers larger) and using and using namespace keywords become convoluted to use. Say you wanted to alias MyProject::DatabaseResultSet as ResultSet and MyProject::DatabaseQuery as Query. You know have to declare two definitions:

using ResultSet = MyProject::DatabaseResultSet;
using Query     = MyProject::DatabaseQuery;

as opposed to using nested namespaces

using namespace MyProject::Database;

Later, you can even implement database driver inside namespaces MyProject::Database::MySQL, MyProject::Database::SQLite, instead of prefixing class names like MyProject::DatabaseMySQLQuery you nest namespaces like MyProject::Database::MySQL::Query and you can alias them as you want, and more importantly, with a single line.

Evenmore, if you have enums you can use simpler and shorter (yet meaningful!) names. C++11's enum class solves some of this issues, worth saying, with a nested namespace for the enum.

enum class Color {
    RED, GREEN, BLUE
}
myObject.setColor(Color::RED);

as opposed to the old

enum Color {
    COLOR_RED, COLOR_GREEN, COLOR_BLUE
}
myObject.setColor(COLOR_RED);

Again, the compiler AND the IDE knows that Color should be and can autocomplete (or provide error messages) that help you a lot.

Things only get worse as the project grows. I don't see it "giving nothing in return".

Namespaces keeps the project modules well defined

Before I start here, I know that you can build a well designed, modular application without nested namespaces, the argument here is: it is better to use them than not.

Look at the Boost libraries, they use namespaces everywhere! First, there's a boost namespace that wraps all libraries. Next, there's a library namespace such as boost::asio things easily get as deep as boost::asio::ip::tcp. That's just beatiful. You know immediatly that you are using TCP/IP. With a little thinking you can even deduce boost::asio::ip::udp should be UDP/IP. Beautiful, beatiful.

Now, think about a game server, in which you have basically 6 big modules: Model, World, Network, Database and Event. (Note: I have used a similar architecture for my l2jserver2 server, in which world, network, database and event are build on top of a service oriented architecture).

The Event module dipatches events that are created by World services. The events are captured Network services and send the relevant events back to to the client.

Nested namespaces can help you keeping this distinction in place: you should not use the GameServer::World objects inside your network code. Neither you should use GameServer::Database inside your network or event modules. You know that if you have any of those declarations inside your code, you have broke the rule.

The bad

The C++ standard comitee had made really hard to use nested namespaces

namespace Namespace1 {
    namespace Namespace2 {
        namespace Namespace3 {
            // ...
        }
    }
}

This can be hard to setup in every header file you need nested namespaces. I only wish the standard would allow things like Namespace1::Namespace2::Namespace3 inside namespaces declarations.

namespace Namespace1::Namespace2::Namespace3 {
    // ...
}

There are several opinions as to how to solve this:

  1. Skip indentation
  2. Use the C-Preprocessor to create macros like NAMESPACE1_NAMESPACE2_NAMESPACE3
  3. Do nothing about it

Solution #1 is ok but Xcode (which is the IDE I use) has issues with identation, if I copy and paste a code, it will paste with proper identation, which is not what I want. Solution #2 is the worst, it does can create subtle problems and you still have to declare the namesapces inside a #define, which is a tediuous job. This leaves solution #3 as the one I choose -- it is not fast, but it is solid. Every C++ programmer will know what was done.

This difficulty comes from their unique initial purpose: avoid name clashes. I don't believe this should be ignored any longer -- nested namespaces are extremely useful and can help avoid complex or convoluted.


Aside from those small downsides to the nesting of namespaces in C++, I don't see any strong reason not to use them: they keep your code organized, modularized, and more importantly, simple. Remember that nested namespaces have an amazing side-effect: they improve your code documentation, it's kind of like some "auto-documenter" in which people don't have to read pages and pages of documentation to find what classes and methods they should use -- but hey, don't you dare stop writing documentation!