This article is part number 5 of the Header files series.


Following up on the previous C++ post, here comes one more thing to consider when writing header files in this language.

using and using namespace

The C++ using directive and its more generic using namespace counterpart, allow the programmer to bring a given symbol or all the symbols in a namespace, respectively, into the calling scope. This feature exists to simplify typing and, to some extent, to make the code more readable. (It may have come into existence to simplify the porting of old, non-ISO C++ code to modern C++, but that’s just a guess.)

The most common use of these that I have seen is to slap a using namespace std; at the beginning of a source file so that all of the symbols in the standard library are available without having to prefix each one of them with std::. So far so good.

Another not-so-common practice is to rarely use this directive and, when using it, place it in the innermost scope where it is needed. In particular, this can make a function much easier to digest:

int complex_computation(... inputs ...) {
    using my_long_namespace::and_another_one::compute_engine;

    compute_engine ce(compute_engine::DO_MAGIC);
    const compute_engine::result r = ce.run(... inputs ...);
    return r.to_integer();
}

Imagine how this function would look like if you had to prefix every instance of compute_engine with my_long_namespace::and_another_one::!

The rule

To recap, using directives in implementation, cpp files, is perfectly fine.

Now, what’s wrong—really, really wrong—is to place a using directive in a header file. These directives exist to be used at the source file level where the programmer has full control of all included headers and their possible conflicts. If header files decide to import names within a namespace into, say, the global scope, it is highly likely that two header files collide. Not to mention that doing so renders namespaces useless!

So: keep all declarations in a header file well-contained into a namespace and do not ever expose those to the global scope with a using directive. Even more: do not ever do this for namespaces you do not control, like std.

The exception

But I think there is a little exception, as usual.

Sometimes, standard libraries from different vendors differ in what they expose via the C++-style headers for standard C functionality. Take vsnprintf(3) as an example. This function is declared in the stdio.h file in C and in the cstdio file in C++. Using the latter should mean that the function is made available only in the std namespace, not globally… but that’s not always the case. Some standard libraries will expose vsnprintf(3) as a global symbol even when using cstdio.

The question is: how do you use this function in your code? Because, depending on the compiler, you will either have to prefix its call with std:: or not. You have two alternatives:

// ----- OPTION 1 -----

#include <cstdio>
#if !defined(HAVE_STD_VSNPRINTF)
namespace std {
using ::vsnprintf;
}
#endif

...

    // Assume it is in std::
    std::vsnprintf(...);

// ----- OPTION 2 -----

#include <cstdio>
#if defined(HAVE_STD_VSNPRINTF)
using std::vsnprintf;
#endif

...

    // Assume it is in ::
    ::vsnprintf(...);

These rely on you being able to define HAVE_STD_VSNPRINTF accordingly, which you can do with a manually-crafted autoconf test or with more complex magic that relies on compiler-defined constants.

What happens when you have to use this function in many different header files, though? Do you repeat this compatibility hack in all of the files you care about, or do you try to code reuse by putting it in a header file? Obviously, the latter is better. But if you do the latter, you really should go for option 1 because option 2 would violate the rule above pretty badly.

Can you think of other exceptions?

Comments from the original Blogger-hosted post: