The Lone C++ Coder's Blog

The Lone C++ Coder's Blog

The continued diary of an experienced C++ programmer. Thoughts on C++ and other languages I play with, Emacs, functional, non functional and sometimes non-functioning programming.

Timo Geusch

5-Minute Read

There, I’ve said it. No tiptoeing around.

As a senior developer/team lead, I get involved in hiring new team members and in certain cases also help out other teams with interviewing people. As part of the interview process, candidates are usually asked to write code, so I review a lot of code submissions. One trend I noticed with recent C++ code submissions is that the first like I encounter in any header file is

using namespace std;

If we happen to review the code submission using our code review system (a practice I’d highly recommend), the above line is usually followed by a comment along the lines of “Timo is not going to like this”. And they’re right, I don’t.

So, why am I convinced that this is really, really bad practice despite a ton of (maybe not very good) C++ textbooks containing the above piece of code verbatim? Let’s for a moment review what the above statement does. Basically, it pulls the whole contents of the namespace “std” (or any other namespace that the author used the using statement for) into the current namespace with no exceptions. And I mean anything, not just the one or two classes/typedefs/templates you’re trying to use. Now, the reason that namespaces were introduced in the first place is to improve modularization and reduce the chances of naming conflicts. It basically allows you to write the following code and ensure that the compiler picks the correct implementations:

std::vector<std::string> names;
my_cool_reimplementation::vector<our_internal_stuff::string> othernames;

Now assume that we’re trying to reduce the amount of typing and put the above using statement in the code (or worse, use both namespaces) and write the following:

vector<string> names;
vector<our_internal_stuff::string> othernames;

If the author of the code is very lucky, the correct implementation of vector will be picked, at least initially. And some time down the road, you’ll encounter strange compiler errors. Good luck finding those - I’ve been in situations where it took days to track down this sort of problem. That’s a heck of a timewaster that you just got for saving to type five characters.

Also, if you’re putting the using statement into the header file, you’re aggravating the problem because the conflicts you will run into sooner or later will be in a module far, far away for no apparent reason until you find out that three layers down, one include file happens to include the file that contains the using directive and suddenly polluted whichever namespace the file contained with the whole contents of namespace std.

So why is

using namespace std;
found in so many textbooks? My theory is that it does reduces visual clutter and also helps with the layout of the book. In a dead tree book, you only have very limited amounts of space so you need to make the most of it. Code examples are generally fairly trivial - well, they have to be if you want the get the point across. Neither of these really hold true when it comes to production code in the age of 24" monitors and text editors that can handle more than 60-80 characters per line (try it, it works!). So, don’t do it.

So, what can you do if you absolutely, positively have to use a using declaration in a header file? There are other ways to reduce the impact of having to do so - you can use one of them, or all of them in various combinations.

First, you can simply use a typedef. I would suggest that this is good practise anyway even if I don’t always follow my own advice. Using a typedef actually has two benefits - it makes a typename more readable and it documents the author’s intent if a well chosen name has been used. Compare the following declarations:

std::map<std::string, long> clientLocations;

typedef std::map<std::string, long> ClientNameToZip;
ClientNameToZip clientLocations;

The second declaration - even though it spans two lines - is much more self documenting than the first one and it gets rid of the namespace fuzz at the same time.

Another option is to limit the scope of the using statement in two ways - only “using” the names of the symbols you need to use, for example:

using std::string;

Again, just throwing this statement into a header file is almost as bad an idea as putting in “using namespace”, so you should limit its visibility by making use of C++ scopes to ensure that your using declaration really only affects the parts of the code that need to see your using declaration in the first place. For example, you could limit the scope to a class declaration:

namespace bar
{
  struct zzz
  {
    
  };
}

Unfortunately what you then can’t do is simply pull in the namespace into a class definition in a header file:

class foo
{
  using namespace bar;

  zzz m_snooze; // *Doesn't* pull in bar::zzz, would be nice though
};

What you can do if the design of your code allows for it is to pull the ‘zzz’ namespace into the namespace that contains class foo, like so:

namespace yxxzzz
{
  using namespace zzz;

  class foo
  {
    zzz m_snooze;
  };
}

This style has the advantage that you’re “only” cluttering a single namespace with your using directive rather than the whole global namespace. At least this way, you are limiting possible naming conflicts to a single namespace. But it’s still a headache if you are using the, err, using directive in a header file this way.

Another way to limit the scope of a using directive to a single function, for example like this:

void temp()
{
  using  namespace std;
  string test = "fooBar";
}

This works in both header and implementation files.

Actually, I would write the above code like this, because there is no good reason (but plenty of bad ones) to pull in the whole std namespace if you only need part of it.

void temp()
{
  using std::string;
  string test = "fooBar";
}

In either case, you are restricting the visibility of a using directive to the part of the code that requires it rather than throwing it right into everybody’s way. The bigger your projects get, the more important it is to ensure proper modularisation and minimise unintended, harmful side effects.

Recent Posts

Categories

About

A developer's journey. Still trying to figure out this software thing after several decades.