Sunday, November 1, 2015

Hatred of the std:: prefix in C++

Among many C++ programmers, there's an extremely strange aversion to using the std:: prefix for names in the standard library (which is why you see C++ code out there littered with the "using namespace std;" statement, and a complete avoidance of the std:: prefix.) There is a common sentiment among these people that the prefix makes the code more unreadable.

This notion is extremely prevalent all the way from complete beginners to university professors teaching C++. Yet I have never seen an actual rational argument for this. It seems to me that these people are just repeating the notion simply because they were taught it, and everybody else is saying it. It's like a form of cargo-cult programming: Hating something for no good reason, simply because everybody else hates it too.

And the thing is, many of these people will defend that notion vehemently, even aggressively. No matter what kind of logical counter-arguments you make, they won't budge.

There is, however, a school of thought that's the polar opposite, and I am a big adherent and promoter of it: Completely avoiding "using namespace std;" and always using the std:: prefix for all standard library names actually makes the code more readable! It also avoids problems.

There are several reasons why this is a good idea.

Firstly, using the std:: prefix for standard library names makes the code more readable for the same reason as code coloring does. You can see at a quick glance where standard library names are being used, and you can more easily see which names are being thus used because they have been "marked" in this manner. Standard library names are thus visually distinct from custom names.

Decades ago I followed the misguided principle of avoiding the prefix, but changed my mind later. And the more I started coding using the prefix, the more I started liking it, and the clearer the code that I wrote became. The "std::" markers really are a very useful visual cue about where and how standard library names are being used, and they distinguish it clearly from my custom names. The more you do this, the more you start liking it, as it really makes the code more readable (which is the exact opposite of the claim.)

Secondly, the prefix actually carries useful information with it. It might not be immediately apparent why, but it really is so. Consider, for instance, this lone line of code:
if ( equal(a, b, c) )
What does this line of code tell us? Not much really. There's a conditional yes, but other than that we have no idea. The "equal()" function could be anything, and we don't know anything about those three parameters. Maybe it's some custom function that compares if three values are equal?

However, contrast it to this:
if ( std::equal(a, b, c) )
Now this is a completely different beast. With the simple addition of the prefix we now know a lot more about this line. Not only do we know now that this is a standard library function, but now we also know that the three parameters are iterators, and we know what this line of code is doing. And even if we didn't know what std::equal() does, we know where to look for that info (rather than going into a wild goose chase in the source code of the program, especially if we are not using an IDE that tells us where that function is declared.)

Thirdly, "using namespace std;" can be problematic because it exposes everything from the standard libraries into the global namespace. This has the danger of causing name collisions. The program might compile now, but just an update to the compiler or its libraries may break it.

POV-Ray is an actual real-life example of this. Prior to C++11, it adhered to the principle of avoiding the prefix, and it used extensively the shared_ptr class from the Boost library. The source code files were littered with these two statements:
using namespace std;
using boost::shared_ptr;
If you are a C++ programmer, you might immediately see what the problem is here.

Somewhere around 2009 or 2010 people started complaining that they couldn't compile POV-Ray from its source code using the latest compilers because of the name collisions between the two versions of shared_ptr. And of course once the C++11 standard was published, it settled the problem for good. Bringing the same name from two different namespaces to the global namespace, just to avoid having to write the prefixes, is a really bad idea.

Yet the hatred of the std:: prefix still prevails to this day. The misinformation and bad practices are being passed from teachers to pupils, and thus they will probably eventually pass this misinformation further, and thus it will be forever perpetuated. This mind virus really needs to stop.

1 comment:

  1. This may, perhaps be due to inertia more than anything else. (Disclaimer: I prefer to use plain old C rather than C++.) When C++ was just starting, there were no namespaces. And people wrote a lot of code that way. When namespaces were introduced, the source code failed to compile. Go figure. To get the code to compile, they could do one of two things. They could find every instance of a standard library function and add the prefix std::. Or they could put "using namespace std;" at the beginning of the file. And then, the ego being what it is, they came up with "reasons" why that was the right thing to do.

    ReplyDelete