The use of double include guards in C++

I am pretty sure that it is a bad practice to add another include guard like:

#ifndef __HEADER_A_HPP__
#include "header_a.hpp"
#endif

Here are some reasons why:

  1. To avoid double inclusion it is enough to add a usual include guard inside the header file itself. It does the job well. Another include guard in the place of inclusion just messes the code and reduces readability.

  2. It adds unnecessary dependencies. If you change include guard inside the header file you have to change it in all places where the header is included.

  3. It is definitely not the most expensive operation comparing the whole compilation/linkage process so it can hardly reduce the total build time.

  4. Any compiler worth anything already optimizes file-wide include-guards.


The reason for putting include guards in the header file is to prevent the contents of the header from being pulled into a translation unit more than once. That's normal, long-established practice.

The reason for putting redundant include guards in a source file is to avoid having to open the header file that's being included, and back in the olden days that could significantly speed up compilation. These days, opening a file is much faster than it used to be; further, compilers are pretty smart about remembering which files they've already seen, and they understand the include guard idiom, so can figure out on their own that they don't need to open the file again. That's a bit of hand-waving, but the bottom line is that this extra layer isn't needed any more.

EDIT: another factor here is that compiling C++ is far more complicated than compiling C, so it takes far longer, making the time spent opening include files a smaller, less significant part of the time it takes to compile a translation unit.


The only benefit I can come up with is that it outright stops the linker from bothering to find the file.

The linker will not be affected in any way.

It could prevent the pre-processor from bothering to find the file, but if the guard is defined, that means that it has already found the file. I suspect that if the pre-process time is reduced at all, the effect would be quite minimal except in the most pathologically recursively included monstrosity.

It has a downside that if the guard is ever changed (for example due to conflict with another guard), all the conditionals before the include directives must be changed in order for them to work. And if something else uses the previous guard, then the conditionals must be changed for the include directive itself to work correctly.

P.S. __HEADER_A_HPP__ is a symbol that is reserved to the implementation, so it is not something that you may define. Use another name for the guard.