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.

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.

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

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.

Here are the errors:

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

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:

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.

, , , Hits for this post: 12966 .
Trackback

only 1 comment untill now

  1. Gravatar

    Undoubtedly genuinely helpful stuff. Many thanks for all the passion to supply this kind of helpful tips here.

Add your comment now