Include guards

From Cppwiki

Jump to: navigation, search

Oh no! My code doesn't work! I get an error about multiple class definitions! Here's what my header, myclass.h, looks like:

// Here is my class, which does things.
class MyClass {
  void DoThings();

The problem occurs when MyClass is defined twice in a single translation unit, which generally happens when myclass.h is included twice. You don't necessarily need #include "myclass.h" twice in a single source file for this to occur - imagine a case where main.cpp includes a.h and b.h, both of which include myclass.h.

The solution, luckily, is easy.

// Here is my class, which does things.
class MyClass {
  void DoThings();

Every time it includes the file, it checks to see if MYPROJECT_MYCLASS is defined. If it isn't, it defines MYPROJECT_MYCLASS - thus ensuring the body won't be included a second time - and then includes the body. If it is, it just skips the rest of the file (down to the #endif).

MYPROJECT_MYCLASS must be unique, otherwise you'll have bizarre issues with files not being included properly. How you guarantee it's unique is up to you - some people include their name, some people include a file path, some people include a timestamp or a random number. (E.g. AUTHOR_YYYYMMDD_HHMM contains some possibly useful information, isn't too long, and - most importantly - has a great deal of permanent global uniqueness.) Often, people start it with an underscore - however, this is incorrect and shouldn't be done, as those are reserved names.

#pragma once

WARNING: Non-Standard Feature This section includes information about a non-standard language extension

"#pragma once" or a similar mechanism, when offered by a compiler, provides the following minor advantages to include guards:

  • Reduces the possibility of various errors (e.g. #ifdef instead of #ifndef, forgetting the closing #endif, dependance of the guard name on the header name, repeating the same unique identifier twice)
  • Does not pollute the global namespace with a macro
  • Is slightly more likely to trigger a mechanism within the compiler which will speed up compilation by skipping over the header if it is included s second time
  • Is slightly faster to type

It also has the following disadvantages:

  • Is not standard C++
  • Is not guaranteed to exist on all compilers
  • Is not nearly as well-known or as common as include guards

The channel ops have mixed opinions regarding the use of "#pragma once".

Opinion: ZorbaTHut
I think it's a bad idea. You get minimal bonuses, and you lose readability and standardization. The macro isn't going to conflict with anything if you choose it properly, there are existing compilers (like GCC) that already do the parse-a-file-once optimization with standard include guards, and typing speed really shouldn't be an issue. The only real problem I see with standard include guards is that once in a while you mess them up - but there are tools that can do them automatically for you and it's trivial to write a test program to verify good include guards. If "#pragma once" was part of the standard I'd probably change my mind, but the fact is that it isn't, and I don't see any reason to violate the standard for such a small benefit.
Opinion: Mikero
The biggest bonuses I see with #pragma once is sped up builds and the eradication of syntax errors that can occur with mistyped include guards. I do agree that in the future, compilers will be smart enough to see include guards for what they are. However, as far as Visual C++ is concerned, the following quote is from the latest MSDN I have, which is as of Aug. 2006: "This can reduce build times as the compiler will not open and read the file after the first #include of the module." Also, syntax errors caused by manual inclusion of erroneous include guards are notoriously difficult to isolate, especially in large code bases. I understand that standard back-tracking error isolation techniques can make this process easier, but consider the case of a lot of changes being made prior to a compile. The resulting set of error messages, especially if the header file erroneously changed was a very common one, could make the problem difficult to find. Most compilers also present cryptic errors when the problem is one of a mistyped include guard and/or an ifdef/ifndef substitution. It is my hope that the once pragma will eventually make itself into Standard C++ and be replaced by what will perhaps amount to a keyword, forcing solitary inclusion of a header.
Opinion: m
I also think using "#pragma once" a bad idea. It makes code unportable for no real benefit. A good compiler will cache the files it read, so re-opening files isn't necessary in the first place. Mistyping include guards doesn't happen, once people manage to configure their text editor right. I wouldn't be opposed to having "#pragma once" or a similar directive in the standard; however, I don't see that happen. I like how it expresses the programmer's intent a lot better than the include guards do. However, as long as "#pragma once" is non-standard, using it is a no-no.
Opinion: Corwinoid
I disagree with adding #pragma once to the standard, on the grounds that it's a #pragma, and therefore specifically a compiler dependant feature. The reasoning for "#pragma once" is noble, however it's a 'restrictive' feature, and disables some multiple-inclusion hacks -- while these are almost never "good", they're often "useful", especially when charting or documenting code, and file relationships. #pragma once violates a number of design choices that C++ is known for, namely that, while promoting safety, it tries not to restrict what the programmer can and can't do. This particular directive does exactly that. It also violates the design rule of minimal interfaces; there's already a mechanism in place for this functionality, and duplicating it doesn't add anything except bloat to the language. That may seem minor, but it's important.

I'm not sure exactly where #pragma once started, it's a historical detail I've never really looked into, so I've always kind of filled in the blanks. I've often thought it was a Microsoft invention, way back in the day of MSC (version 3, I think), and so I've always taken the same tact to using it that MS uses in their own headers. Nominally, they acknowledge that it's a non-standard, non-portable feature, and take steps to insure that it's only invoked when run through their own compiler, by wrapping it in a unique set of preprocessing checks. Regardless, they still use classic inclusion guards on all of their headers.

The only major benefit to #pragma once is that, for compilers that support it, and don't already do exclusive-multiple-inclusion avoidance, is that it lets the preprocessor know not to recurse the file again, at all. In my opinion, the speed gains are minimal, giving it limited advantage over the alternative. Since it's non-portable, and non-standard, it's also not a replacement. Even if you choose to use #pragma once, your headers should still be wrapped with inclusion guards.
Personal tools