Avoid using directives in header files

It is often that I see people using namespace directives in header files. This is a bad practice maybe not enought explained, so I will try to clarify why one should always avoid this.

When you are using a using directive (such as using namespace std) or using declarations (such as using std::cout) you are bringing into the current namespace (either the global one or a named one) all the entities from the specified namespace (in the case of a using directive) or the entities specified with using declarations. Header files are meant to be included in sources files (usually more that just one source file) and the order of the include statements is most likely different.
If entities (types, functions, constants, etc.) with coliding names are brought into the same translation unit (source file) via different header files then the compiler will trigger errors due to ambiguities.

The following example will demonstrate this aspect. Suppose that you have an own list implementation in a file called mylist.h.

#pragma once 

namespace mycontainers 
{
   class list
   {

   };
}

and you make use of this container in a class called foo, but in the header you are using a namespace directive to avoid writing the fully qualified name for list.

#pragma once 
#include "mylist.h"

using namespace mycontainers;

class foo 
{
   list mylist_;
};

However, a second class, called bar, is using the STL list, and also using a namespace directive.

#pragma once 
#include < list >

using namespace std;

class bar 
{
   list< int > mylist_;
};

All good as long as you use foo and bar separatelly. But the moment you need to include them both in the same source file (maybe directly, maybe via another headers) errors arise.

#include "foo.h"
#include "bar.h"

int main()
{
   foo f;

   return 0;
}

Here are the errors:

1>d:mariusvc++win32_testbar.h(9) : error C2872: 'list' : ambiguous symbol
1>        could be 'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'
1>        or       'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'
1>d:mariusvc++win32_testbar.h(9) : error C2872: 'list' : ambiguous symbol
1>        could be 'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'
1>        or       'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'

Of course, if you switch the order of #includes in you get another error:

1>d:mariusvc++win32_testfoo.h(8) : error C2872: 'list' : ambiguous symbol
1>        could be 'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'
1>        or       'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'

A second, more hard to spot error is explained by Sutter and Alexandrescu in C++ Coding Standards – 101 Rules, Guidelines, and Best Practices.
When you make use of a using declaration (using std::list), a snapshot of the used entity is taken. All later references to this entity are based on this snapshot. They provide the following example:

// sample 1
namespace A
{
   int f(double);
}

// sample 2
namespace B
{
   using A::f;
   void g();
}

// sample 3
namespace A
{
   int f(int);
}

// sample 4
void B::g()
{
   f(1);
}

When using A::f is encounted, a snapshot of A::f is taken from what was found so far. Only f(double) was declared already, f(int) is found only later.
So though this later overload was a better match for f(1) it would be ignored, because it wasn’t known at the time of the using declaration.

This issue complicates more if each of the first 3 samples were in different files. Then the order of the $include directives in the file that contains the 4th sample would dictate which overload of f() to be used.
And if sample 4 was itself in a header, other that the first 3, the order of the includes would become even more critical.

For these reasons, you should keep in mind never to use namespace directives or declarations in a header file. Instead use the fully qualified name for the types, functions, constants, etc. that you use, and leave the using directives for the source file exclusively.

1 Reply to “Avoid using directives in header files”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.