Logo

Blog


Use namespaces

Today's post is motivated by some past discussion that came up during standardization. The renaming of two views back to their originally proposed names P2501R0. One was a rename from views::all_move to views::move.

I'm not speaking or expressing the opinion of the committee here.

The rename was subject to a debate about whether it was a good idea. One reason for being against the undo of the rename was that the standard now has a std::move and a std::views::move. Two times the name move but is well guarded in different namespaces. Of course, with different functionality as well.

The argument for keeping all_move was to protect people who write code like this:

1
2
3
4
using namespace std;
using namespace std::views;

auto x = move(y);

In this example, the author used using namespace to get rid of the repetitive typing std:: and, of course, std::views::.

By doing this, the compiler now finds two functions move and picks the best matching one. However, the best match in terms of the language, not our expectations. In the case of all_move, the std::move version is picked unintentionally.

So far about the introduction.

Let's forget about the proposal. My point is about using namespace.

Dragging in an entire foreign namespace is bad practice! You must be prepared for trouble if you deliberately pull in a whole, foreign namespace. The key idea behind a namespace is encapsulation. Sparing you trouble. Once you ignore that, the potentially resulting problem is entirely on you.

When is it okay to say using namespace?

My rule I use is to use using namespace once I implement a class in a namespace. For example, suppose you I have the following header file:

1
2
3
4
5
6
7
// header file
namespace Cool {
  class Apple {
  public:
    void Fun();
  };
}  // namespace Cool

I would use using Cool in the implementation as this is my namespace.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// implementation file

#include "cool.h"

using namespace Cool;

void Apple::Fun()
{
  // impl
}

What if I need a function or data type from a foreign namespace often?

Sometimes you use functions or data types from other namespaces a lot in a certain implementation file. As an example, assume std::move. Please don't say using namespace std;. The better solution here, if you really like to avoid typing std, is

1
using std::move;

By that, you make only std::move visible in your current file. Hopefully, when you write directly beneath that statement, another one using std::views::move, it becomes apparent that you're asking for trouble.

However, I personally have to rule to avoid using for foreign data types. Such symbols are, for a reason, in their own namespace. The following are my personal set of rules for namespaces:

  1. Avoid using namespace for foreign types/functions.
  2. Use using namespace only for the namespace you currently provide an implementation for.
  3. If you fight with long foreign namespaces prefer using DATATYPE_OR_FUNCTION; over using namespace.
  4. Stay away from using namespace.
  5. Always be precise, even on slides.

Do you want some exercise?

In case you want a little exercise, have a look at the following code and answer yourself:

  1. Does this code compile?
  2. What is the output of that program?
  3. Would the output change if you would change the two using lines?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <cstdio>

namespace a {
  void Fun()
  {
    printf("a::Fun\n");
  }
}  // namespace a

namespace b {
  void Fun()
  {
    printf("b::Fun\n");
  }
}  // namespace b

void Fun()
{
  printf("Fun\n");
}

int main()
{
  using a::Fun;
  using namespace b;

  Fun();
}

Of course, Compiler Explorer know the truth.

Andreas