"using namespace" in c++ headers

96,204

Solution 1

You should definitely NOT use using namespace in headers for precisely the reason you say, that it can unexpectedly change the meaning of code in any other files that include that header. There's no way to undo a using namespace which is another reason it's so dangerous. I typically just use grep or the like to make sure that using namespace isn't being called out in headers rather than trying anything more complicated. Probably static code checkers flag this too.

The header should include just the headers that it needs to compile. An easy way to enforce this is to always include each source file's own header as the first thing, before any other headers. Then the source file will fail to compile if the header isn't self-contained. In some cases, for example referring to implementation-detail classes within a library, you can use forward declarations instead of #include because you have full control over the definition of such forward declared class.

I'm not sure I would call it common, but it definitely shows up once in a while, usually written by new programmers that aren't aware of the negative consequences. Typically just a little education about the risks takes care of any issues since it's relatively simple to fix.

Solution 2

Item 59 in Sutter and Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices":

59. Don’t write namespace usings in a header file or before an #include.

Namespace usings are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.

Corollary: In header files, don't write namespace-level using directives or using declarations; instead, explicitly namespace-qualify all names.

A header file is a guest in one or more source files. A header file that includes using directives and declarations brings its rowdy buddies over too.

A using declaration brings in one buddy. A using directive brings in all the buddies in the namespace. Your teachers' use of using namespace std; is a using directive.

More seriously, we have namespaces to avoid name clash. A header file is intended to provide an interface. Most headers are agnostic of what code may include them, now or in the future. Adding using statements for internal convenience within the header foists those convenient names on all the potential clients of that header. That can lead to name clash. And it's just plain rude.

Solution 3

You need to be careful when including headers inside of headers. In large projects, it can create a very tangled dependency chain that triggers larger/longer rebuilds than were actually necessary. Check out this article and its follow-up to learn more about the importance of good physical structure in C++ projects.

You should only include headers inside a header when absolutely needed (whenever the full definition of a class is needed), and use forward declaration wherever you can (when the class is required is a pointer or a reference).

As for namespaces, I tend to use the explicit namespace scoping in my header files, and only put a using namespace in my cpp files.

Solution 4

Check out the Goddard Space Flight Center coding standards (for C and C++). That turns out to be a bit harder than it used to be - see the updated answers to the SO questions:

The GSFC C++ coding standard says:

§3.3.7 Each header file shall #include the files it needs to compile, rather than forcing users to #include the needed files. #includes shall be limited to what the header needs; other #includes should be placed in the source file.

The first of the cross-referenced questions now includes a quote from the GSFC C coding standard, and the rationale, but the substance ends up being the same.

Solution 5

With regards to "Is there some way to undo [a using declaration]?"

I think it is useful to point out that using declarations are affected by scope.

#include <vector>

{   // begin a new scope with {
    using namespace std;
    vector myVector;  // std::vector is used
}   // end the scope with }

vector myOtherVector;   // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified

So effectively yes. By limiting the scope of the using declaration its effect only lasts within that scope; it is 'undone' when that scope ends.

When the using declaration is declared in a file outside of any other scope it has file-scope and affects everything in that file.

In the case of a header file, if the using declaration is at file-scope this will extend to the scope of any file the header is included in.

Share:
96,204
Baruch
Author by

Baruch

Updated on December 11, 2020

Comments

  • Baruch
    Baruch over 3 years

    In all our c++ courses, all the teachers always put using namespace std; right after the #includes in their .h files. This seems to me to be dangerous since then by including that header in another program I will get the namespace imported into my program, maybe without realizing, intending or wanting it (header inclusion can be very deeply nested).

    So my question is double: Am I right that using namespace should not be used in header files, and/or is there some way to undo it, something like:

    //header.h
    using namespace std {
    .
    .
    .
    }
    

    One more question along the same lines: Should a header file #include all the headers that it's corresponding .cpp file needs, only those that are needed for the header definitions and let the .cpp file #include the rest, or none and declare everything it needs as extern?
    The reasoning behind the question is the same as above: I don't want surprises when including .h files.

    Also, if I am right, is this a common mistake? I mean in real-world programming and in "real" projects out there.

    Thank you.

  • Anthony Hall
    Anthony Hall over 7 years
    This is a useful technique I hadn't seen before; thanks. Normally I've been fine with using full scope qualification, and putting using declarations inside function definitions where I can so they won't pollute namespaces outside the function. But now I'm wanting to use C++11 user-defined literals in a header file, and per the usual convention, the literal operators are protected by a namespace; but I wan't to use them in constructor initializer lists that aren't in a scope that I can use a non-polluting using declaration. So this is great for solving that problem.
  • Anthony Hall
    Anthony Hall over 7 years
    Although an unfortunate side effect of this pattern is that any classes declared inside the innermost namespace will show up in compiler error messages with the fully qualified name: error: ... DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED:: DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED::ClassName .... At least, that's what's happening for me in g++.
  • rustypaper
    rustypaper over 7 years
    you seem to be the only one how understood the actual question... however, my compile is not very happy about me using inside the class deceleration.
  • Chris
    Chris over 6 years
    are we free to use using statements in our .cpp files? the 3rdPartyLib::BigClassName<3rdPartyLib::AnotherBigName,3rdPar‌​tyLib::AnotherBigNam‌​e>::Iterators are death to the fingertips.
  • Chris
    Chris over 6 years
    and how should we streamline the template functions--which are supposed to be in the headers? typedefs?
  • Chris
    Chris over 6 years
    how do you streamline template function declaration? that has to occur in the header, no?
  • TafT
    TafT over 5 years
    This answer could be made even better by explaining the problem with the OP's idea of how scope should work (like the namespace declaration stuff) vs. how it actually works (like a variable). {} enclsing it limit its scope, {} after it do nothing relating to it. That is an accidental way that the using namespace gets applied globally.
  • tjwrona1992
    tjwrona1992 about 5 years
    @donlan, it seems you got no response for quite a while... Yes, you can use using statements within .cpp files without much concern because the scope will be limited to just that file, but never do it before an #include statement. As for template functions defined in headers, unfortunately I don't know of a good solution other than just writing out the namespace... Perhaps you could put a using declaration within a separate scope { /* using statement in between brackets */ }, that would at least prevent it from escaping the current file.