What is a namespace

A namespace is a general concept, which you can find across different programming languages. It is a language structure, which helps you:

  1. logically group classes and other entities (functions, constants, static variables, enums, etc.);
  2. avoid name conflicts;
  3. hide implementation details.

All professionally written software uses namespaces. To open a namespace just write:

Namespaces could be nested:

Since C++ 17  you can also write:

Let’s have a closer look how a namespace can be useful with some examples.

Logical grouping

It is always good to show explicitly, which modules and submodules your application has. Except for separation by using folders or projects (in Visual Studio), you can use namespaces for this purpose. And, naturally, the same namespace can be used across different folders and projects. Put logically connected members in the same namespace. Maybe you will also want to have some policies, for example, in “simulations_visualisation” namespace is not allowed to use members from “device_signals_processing” namespace in order to keep abstraction layers independent and clear.

Avoiding name conflicts

It is very simple to get the situation when the name you use in your application is the same as in some third party library you just referenced. Or if you are a library developer, you cannot guarantee, that the names you expose in a public API will be unique for every application which uses your library.

If there is an ambiguity which variable/class/function to call, a compiler will complain in some manner. It could generate either compile-time errors like “ambiguous call to overloaded function” or linking-time errors like “(colliding name) already defined”. That’s exactly the situation when namespaces are handy.

Although, it does not prevent from name clashes when the namespaces names are same as well. So try to think about good, descriptive and not extremely widely used words for your namespaces names.

There is one more problem when your application will be successfully compiled and run. It is accidentally declaring overloaded functions: the function with the same name (e.g. as in STL), but, for instance, with more specific argument types. The last one will be always called if the arguments are just as expected.

The namespaces help to resolve this issue, but it is better to avoid such functions “overloading”.

No namespaces at all?

There are a lot of languages, which does not have a namespace concept. And C programming language and  Objective-C are among of them.
Some of the libraries, like Qt, do not use namespaces to make their names unique, but rather add a “Q” prefix to every single user class: QString, QFlags, QFileInfo etc. You can also use this technique, but I personally find it even more frustrating then namespaces (and you have only 26 letters for a gigantic pool of software and libraries. You can go further and combine 2 letters, 3 letters, add numbers, … now it becomes totally unreadable☢. In a very small number of cases, a prefix out of 2 characters can be meaningful for your library and expressive at the same time.

Encapsulating code inside anonymous namespaces

Let’s consider the following situation. We have two classes. In their .cpp files, except declared in headers members, we want to implement some .cpp-local members:

If you try to compile this, you will get a linking error: [email protected][email protected]@YAXXZ) already defined in MyClass.obj”. To fix such problems and in order not to pollute your namespace, just wrap the non-interface members in an anonymous namespace:

Scopes

If you do not use any namespace, you are in the global scope.

Do not wrap the main function in any namespace, because the environment will be unable to find your application entry point. The compiler will actually generate a linking error like “unresolved external symbol _main referenced in function ___tmainCRTStartup”.

“::” called the scope resolution operator. If there is no :: operator on the left-hand side of the name, the “closest” declaration with such name will be taken. Hence, if you want to refer to some specific variable – specify it’s lookup name.

Scopes and forward declaration

One more notice about names lookup. If you make a forward declaration of some object and occasionally put it inside your namespace – it means the new nested namespace declaration. All the occurrences of this namespace further in your code will force to lookup names inside your newly declared nested namespace (and normally find nothing).

The compiler error here will be ‘unique_ptr’: is not a member of ‘my_namespace::std’. The std::unique_ptr lookup starts from my_namespace, then finds std namespace you have put inside it and, of course, there is no unique_ptr member in this inner namespace. Hence the correct forward declaration must be outside of your namespace, unless you forward declare some nested namespace member.

Inline namespaces

Inline namespaces may be useful for library developers. Let me give you an example. For a long time ago, you have developed a library for traders, to make their trades using your API. Then you worked hard and developed a new, more fast and robust logic for sending orders in your OrderManager class. Of course, you want to have a backward compatibility for your clients, which use the old version of the OrderManager. There are several options what to do:

  • introduce a new class like OrderManager2. Not very elegant solution and how new users should figure out which one to use?
  • wrap the old OrderManager in a namespace v_1, and add a new one to namespace v_2:

    Congrats, you just have broken the API and instead of
    trading_monster_lib::OrderManager om;
    your users have to write
    trading_monster_lib::v_1::OrderManager om;

    And again, it does not eliminate the confusion about which version to use.

  • use inline namespaces.

All the members introduced in an inline namespace become actually the members of the surrounding namespace. So adding inline keyword before your namespace will import all it’s members to the enclosing namespace.

As a result, your new users will use v_2 as a default version. The old users will still need to make changes in their code, but only if they want to use the old v_1 version. If they are fine with the new one – no need to change anything.

One more use-case is choosing which namespace to inline, depending on some compile-time condition:

We can use a compile-time condition to specify whether to inline a namespace or not:

Further considerations

Use namespace aliases

One of the disadvantages with the namespaces is that writing names with their full namespaces qualification add a lot of clutter.

The mitigation could be the following: try to think of short namespace name (if you are designing the code) or use aliases to shorten long namespace qualifiers.

You can still save on typing and decrease clutter

It is generally not very good idea to write “using namespace std;” (or any other namespace, except your own) in a .cpp file. That is because it will import all the names from that namespace. And never even think to write it in a header: names scope of any file, which includes this header (explicitly or implicitly via another header) will be polluted with that namespace members.

What we can do to save on typing, is still use “using” but only for particular names rather than the whole namespace:

Or you can also import the whole namespace, but very locally, say, inside a function:

 

That was it. Thank you for reading this really long tutorial to the end. I wish you certainty and expressiveness in your code!

 

The ultimate C++ Namespaces Tutorial
Tagged on:             
newest oldest most voted
Notify of