Question

I understand the rationale of avoiding using namespace std - this defines too many casual names the developer may not be even aware of.

I tried to work around the problem with the help of using construct. Most often, I it was using std::string and using std::vector, because these are really very common cases and writing std:: everywhere seems cluttering the code a lot. During the code review, it was pointed out that if I do this in the headers, the definitions propagate over many files without obvious consent, as the headers files tend to include one another. In response, I removed all using statements from the headers but moved them into .cpp files where the most of the code reside anyway. However during the next code review I was told to remove them from there as well.

I still have some doubts if using on the top of the cpp file that is never included into another file still may have big negative consequences. It seems to me that having no namespace prefixes for very common case like string or vector makes the code easier to read.

I would like to clarify, if the current major consensus in C++ community really discourages putting some common names (using std::vector and using std::string) of the std:: namespace on the top of the .cpp (not header) file. If this is really the case, it would be good to know why.

Was it helpful?

Solution

using directives are certainly acceptable in *.cpp files when C++ authorities like Herb Sutter and Bjarne Stroustrup explicitly say so in their published Core Guidelines:

Use using namespace directives for transition, for foundation libraries (such as std), or within a local scope (only)

However, I believe your question is based on a false premise. You say that prepending std:: to identifiers everywhere clutters the code. This is purely subjective, and most C++ programmers I know (including myself) have the opposite view, i.e. that the std:: makes the code easier to read because standard-library components can easily be distinguished from your own classes and functions.

Now of course, this opposite opinion might be equally subjective, but you also have to consider consistency. After all, you avoid using directives at global scope in header files anyway, so why add different rules for different situations? As a C++ programmer, you are used to seeing std::string and std::vector in header files all the time, so string and vector simply look unusual, even in *.cpp files.

OTHER TIPS

In addition to the other, good and balanced, answer:

  • In headers global scope, I'd say it's quite the consensus to not use using namespace XYZ
  • I don't see any such consensus with regard to source/cpp files: I.e. some find it OK, some frown upon even this.
  • using namespace std or using std::string can be scoped to a local function/scope, which is what I prefer: That way I can even use it in header-inline functions.
  • If I have a function and I use string once, I can just as well write std::string. If the function uses string, vector, ... in multiple places, I prefer the using form.
    • I do find too many :: clutter my code.

I don't know about community consensus but I've come to favor not only using declarations but using directives (ex: using namespace std;) in source files (not for headers, of course, at namespace scope). At least Sutter seems to share the same wavelength. From his C++ Coding Standards:

You can and should use namespace using declarations and directives liberally in your implementation files after #include directives and feel good about it. Despite repeated assertions to the contrary, namespace using declarations and directives are not evil and they do not defeat the purpose of namespaces. Rather, they are what make namespaces usable. -- Herb Sutter

I didn't always favor using directives let alone declarations. When I started using C++ some 25 years back or so, I favored the more verbose and explicit style since my rationale was that I could use the exact same style in headers and source files. However, the main reason I wanted to pitch in was to share some experience dealing with real bugs in production code that came from failing to use the proper namespace(s). I've encountered at least a good dozen or two in my career, and some were very painful.

I've forgotten most of the precise details of each one, but they all had to do with using the wrong overload of a function or operator (ex: a generic version) from the wrong namespace combined with argument-dependent lookup which satisfied the compiler but produced the wrong runtime behavior. These were all in massive codebases spanning millions of LOC. All of them could have been easily avoided with using directives, and it was after encountering the first few of such bugs that I began favoring and even promoting using directives for source files.

The one I remember very clearly but was actually the most trivial to detect and fix was a case where I found some code where a third-party dev whose source we acquired had included <cmath>, but used the wrong version of abs. The dev forgot to put std:: in front and passed in a floating-point parameter, only to get back an integer result cast back to floating-point from the version of abs that C defines in the global namespace. That was one of the simpler cases and I ended up debugging his code and fortunately found it quickly by looking at the compiler warnings, but it's yet another example of how omitting using directives and declarations in source files can lead to actual runtime bugs and grief for our customers.

Meanwhile, I've been using C++ for such a long time, and have worked in the widest variety of codebases ranging from the foulest with shoddy standards and testing procedure to reasonable ones, and there was only one time where I encountered a clash resulting from using directives. Just one for people concerned about using directives/declarations possibly resulting in clashes. It was one time in the 90s when we ported our product to CodeWarrior for the Mac, and CodeWarrior had some standard header which defined an identifier like Polygon in the global namespace which clashed with one we used from our own namespace. Took like 15 minutes to fix and was a simple compiler error, not a runtime bug. So from my standpoint, using directives and declarations in source files can actually prevent human mistakes from turning into bugs, while any rare clash that might result from that is most likely just going to result in a simple compile-time error.

Licensed under: CC-BY-SA with attribution
scroll top