On the proper use of using namespace

Using namespaces correctly in C++

I very often see the concept of namespace being misused. I often explain on forums why you should absolutely avoid writing things like using namespace. Here is an exhaustive tutorial on why I strongly advise against this practice.

In this tutorial, I will discuss the concept of namespaces. Indeed, I very often see C++ programmers using them incorrectly. Let’s get straight to the point: never use using namespace, ever!

I will divide this tutorial into three parts:

  • A reminder.
  • Why not to use it.
  • What to replace this clause with.

Reminder

Namespaces

First, a reminder of what a namespace is. A namespace is, as its name suggests, a restricted space where you can store functions or variables without fear of conflicts. In C, when you want to create a new function, you have to make sure that it does not conflict with another one, and therefore give it a different name if necessary.

Example:

void system_display(void);
void my_display(void);

Why not give them the same name? After all, even if a function already exists, it is legitimate to be able to choose the name we like. It is to solve this problem that namespaces were invented.

Example:

namespace system
{
  void display(void);
}
namespace my
{
  void display(void);
}

Here, we can see that the problem is solved more elegantly, since the name of the function has not been modified due to technical constraints. When using it, you just need to specify the namespace.

Example:

system::display();
my::display();

After this brief reminder, let’s now move on to the problem at hand.

Code cleanliness and clarity, the case of std

You have to remember that the standard C++ functions are coded by (talented) people and that this namespace is reserved for them. By typing using namespace std;, it’s almost like doing:

namespace std
{
  // Code
  int main()
  {
    // Code
    return 0;
  }
}

It’s almost, and I mean almost, as if you were coding directly in the std space! Suffice to say that you have no business being here. From a cleanliness point of view, this is not it.

Finally, from a code clarity point of view, the namespace is often useful information, since it allows you to know at a glance the context of what you are using. If I see “std::”, I immediately know that I am calling something standard from C++. Similarly, if I see “boost::”, I know that I am using Boost.

Finally, why would you want to “get rid of” this very practical feature? Some will answer that we save 5 characters. Yes, but at what cost? Are you really 5 characters short? I would like to remind you that if the “std” namespace is named like that, and not “standard”, there was a reason… But okay, let’s keep the argument, and see what it can cost.

The dangers of “using namespace”, or why not to use it

This clause, used to save time, can actually waste a lot of it. We will see several problems:

Namespace conflicts, or how to pull your hair out

Let’s just take the following code:

#include <iostream>
#include <cmath>

double abs(double)
{
  return -1;
}

int main()
{
  std::cout << abs(-4.5) << std::endl;
  std::cout << std::abs(-4.5) << std::endl;

  return 0;
}

Here, no surprise. The code compiles well, and does what we want. Now, the version with using namespace:

#include <iostream>
#include <cmath>

using namespace std;

double abs(double)
{
  return -1;
}

int main()
{
  cout << abs(-4.5) << endl;
  cout << std::abs(-4.5) << endl;

  return 0;
}

We will have compilation problems here. Indeed, the abs function conflicts with the std::abs function. The error is not very difficult to correct, you just have to indicate what you want to use, explicitly (write ::abs). Now, imagine that you are using a library made by a third party. If you “get rid of” the namespaces, you are very likely to pull your hair out because of compilation problems. Tell yourself that this is a very simple example of a problem induced by the use of this clause. On large projects, this type of error can be much more difficult to detect.

Name shadowing, a source of error

Let’s take the following code:

#include <iostream>

int min(float, float)
{
  std::cout << "Enter min" << std::endl;
  return -1;
}

int main()
{
  std::cout << min(45.6, 5) << std::endl;
  std::cout << min(45, 3) << std::endl;
  return 0;
}

This simple code will display:

Enter min
-1
Enter min
-1

Indeed, we obviously expect to enter the “min” function that we created, and which always returns -1.

Let’s do the same code, with a using namespace clause:

#include <iostream>

using namespace std;

int min(float, float)
{
  cout << "Enter min" << endl;
  return -1;
}

int main()
{
  cout << min(45.6, 5) << endl;
  cout << min(45, 3) << endl;
  return 0;
}

Do you expect the same result? Well no!

The result will be:

Enter min
-1
3

This is completely unexpected, but ultimately quite logical. Indeed, the std::min function exists! By getting rid of the namespaces, we have implicitly triggered the use of this function. Since we are using integers, and not “float”, the compiler thought it would be wise to use the std::min function which is more suitable for taking “int, int” arguments.

No error is shown to you, nor any warning since this is perfectly valid C++, technically. What I am trying to show you here is that you cannot know everything that is in the std namespace. On the one hand because there are many things, on the other hand, because C++ is a language that evolves, and it is highly possible that things will be added in the future. Your code may be potentially incompatible with future versions of C++ if you misuse namespaces.

Of course, some will argue that I could write ::min instead of min, which would solve the problem. This is quite correct, but honestly, how much time will you spend discovering a problem of this kind on a large project?

In the same vein, shadowing can be done the other way around:

Example:

#include <iostream>
int main()
{
  int hex = 0;
  std::cout << std::hex << 42 << std::endl;

  return 0;
}

This code will of course display: 2a. Now the version with the using namespace clause:

#include <iostream>
using namespace std;
int main()
{
  int hex = 0;
  cout << hex << 42 << endl;

  return 0;
}

This code will display: 0. Indeed, the compiler does not know whether to take std::hex or the hex variable. It takes the “closest” one, that is to say the hex variable. We have a shadowing here. To solve it, nothing could be simpler, just put std::hex.

The worst thing to do

Using a using namespace clause can have limited impacts in a code file, but if you indicate it in a header file, then the impacts can be catastrophic. If you develop in a team, or if you create a library that you are going to distribute, anyone who includes your work will see their namespaces “removed” when they have not asked for anything!

What to replace the using namespace clause with?

Now that we have seen why you should never use a “using namespace” clause, let’s see how to replace it intelligently.

To counter my own argument, it is true that it is sometimes more readable to read code that is not permanently prefixed. This is particularly the case for certain libraries like boost::spirit, which emulates a BNF grammar in the most visual way possible. It would be frankly unpleasant to have to indicate namespaces in front of each of the rules, since that would break the attempt at resemblance. This is just one example among others, and we will see how to remedy it with elegance.

Aliasing

In the case of a prefix name that is too long, it is possible to make an “alias”. That is to say, to make a kind of “typedef” on a namespace. A namespace not being a type, but a separate mechanism, the syntax is obviously different.

If I take the following example:

#include <iostream>
int main()
{
  std::cout << "Hello World!" << std::endl;

  return 0;
}

Nothing prevents me from creating an alias on std, to shorten it:

#include <iostream>

namespace s = std;

int main()
{
  s::cout << "Hello World!" << s::endl;

  return 0;
}

This technique is used a lot with Boost, which sometimes has long namespace names.

Example:

namespace po = boost::program_options;
void usage(const po::options_description& desc)
{
  std::cout << "Version: " << desc;
}

A limited scope

One of the possible solutions is the use of the using namespace clause in a limited scope. Meaning within a function itself, or a namespace.

Example:

#include <iostream>

namespace
{
  using namespace std; // Effective only in the anonymous namespace

  void hello()
  {
    cout << "kikoo" << endl;
  }

  void pouet()
  {
    cout << "pouet" << endl;
  }
}

void test()
{
  using namespace std; // Effective only in the test function

  cout << "pouet" << endl;
}

int main()
{
  // Not affected by using namespace std;
  std::cout << "Hello World!" << std::endl;

  hello();
  pouet();
  test();

  return 0;
}

Unfortunately, this technique does not solve all the problems. A more rigorous method is necessary, and that is the subject of my next point.

A controlled scope

Let’s take one of the problems already stated by putting the clause in a limited scope:

#include <iostream>

int min(float, float)
{
  using namespace std;
  cout << "Enter min" << endl;
  return -1;
}
int main()
{
  using namespace std;
  cout << min(45.6, 5) << endl;
  cout << min(45, 3) << endl;
  return 0;
}

The problem is still not solved. Here, the problem is not due to a scope, but to a non-selective choice made by the programmer. The solution is simply to choose explicitly what you want to import:

#include <iostream>

using std::cout;
using std::endl;

int min(float, float)
{
  cout << "Enter min" << endl;
  return -1;
}
int main()
{
  cout << min(45.6, 5) << endl;
  cout << min(45, 3) << endl;
  return 0;
}

The problem is now solved, since we have not explicitly authorized the replacement of min by std::min. Here, we can clearly see that the controlled declaration of each of the symbols makes it possible not to create a problem due to a “wild import” of the symbols from std.

A limited and grouped scope

The only drawback of this technique, which is not really one, is that it is sometimes longer to write one by one, each of the symbols that we no longer want to prefix. It is often out of laziness that programmers use “using namespace”. However, this reason is not valid: it is possible to have your cake and eat it too! Indeed, it is quite possible to group the directives under the aegis of a single one, in order to write only one line.

Example:

#include <iostream>

namespace mystd // Can be put in a header
{
  using std::cout;
  using std::endl;
}

int min(float, float)
{
  using namespace mystd;
  cout << "Enter min" << endl;
  return -1;
}

int main()
{
  using namespace mystd;
  cout << min(45.6, 5) << endl;
  cout << min(45, 3) << endl;
  return 0;
}

The small problem with this technique is that it does not avoid all errors.

A limited and controlled scope

Let’s take an example already seen above, using the limited scope technique.

#include <iostream>

int main()
{
  using namespace std; // or using namespace mystd; as seen above,
                       // but with using std::hex in it as well
  int hex = 0;
  cout << hex << 42 << endl;

  return 0;
}

Here, we have the using namespace which is only active in the main function, but it unfortunately does not prevent the shadowing of arguments. It would have been nice of the compiler to tell us that the hex variable is likely to create a conflict.

Fortunately, this system exists. Rather than using the using namespace clause, prefer the “simple using” clause in a limited scope. I can only advise you to use this technique, without using the grouping seen above. The use of this technique will allow you to have fine control over what you are doing. Let’s apply this to our famous example:

#include <iostream>

int main()
{
  using std::hex;
  using std::cout;
  using std::endl;

  int hex = 0;
  cout << hex << 42 << endl;

  return 0;
}

And there, miracle, the compiler warns us:

 error: 'int hex' redeclared as different kind of symbol

This technique therefore has the advantage of warning us in case of argument shadowing.

Conclusion

I have detailed the reason why the use of using namespace is to be absolutely proscribed. I hope that thanks to this tutorial, you will use namespaces with a little more control. The big problem is that some bad uses are very present on the net, or even in the classroom!