398

I'm working on a codebase that is known to only run on windows and be compiled under Visual Studio (it integrates tightly with excel so it's not going anywhere). I'm wondering if I should go with the traditional include guards or use #pragma once for our code. I would think letting the compiler deal with #pragma once will yield faster compiles and is less error prone when copying and pasting. It is also slightly less ugly ;)

Note: to get the faster compile times we could use Redundant Include Guards but that adds a tight coupling between the included file and the including file. Usually it's ok because the guard should be based on the file name and would only change if you needed to change in the include name anyways.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Matt Price
  • 38,782
  • 9
  • 34
  • 43

13 Answers13

354

I don't think it will make a significant difference in compile time but #pragma once is very well supported across compilers but not actually part of the standard. The preprocessor may be a little faster with it as it is more simple to understand your exact intent.

#pragma once is less prone to making mistakes and it is less code to type.

To speed up compile time more just forward declare instead of including in .h files when you can.

I prefer to use #pragma once.

See this wikipedia article about the possibility of using both.

Brian R. Bondy
  • 314,085
  • 114
  • 576
  • 619
  • 33
    According to wikipedia, some compilers optimize pragma once, some (like gcc) also optimize include guards. My gut says go with whatever system your code is already using. I use BOTH pragma once and guards. – KitsuneYMG Jul 17 '09 at 15:32
  • 5
    It can make a significant difference in compile time because the C preprocessor doesn't have to be involved - the compiler itself can decide not to even open the file. Opening files over and over takes cycles. – Donnie DeBoer Jul 17 '09 at 15:32
  • 10
    @Donnie - that is the optimisation which gcc's preprocessor applies to include guards. It automatically detects include guards in header files, and if there is one it treats the file as though it had #pragma once. If it's included again, and the include guard has not been undefined in the mean time, then the file is not re-opened or re-parsed. – Steve Jessop Jul 17 '09 at 15:39
  • True, but the question poster is using VC++, so using #pragma once may result in faster compilation. – Donnie DeBoer Jul 17 '09 at 15:52
  • Oh, I see what you mean. Sorry, I thought you were responding to kts's comment. About "some compilers (like gcc)". Clearly you're in fact responding to Brian's first sentence. Ignore me. – Steve Jessop Jul 17 '09 at 17:40
  • I put that bit about "some compilers" because I do not know what VC++ does (since I use both pragma once and guards) it has never mattered, and because MS could decide to remove/change pragma once behavior since it isn't required by the standard. Why they might do this I don't know, but it wouldn't be the first time they've made old code incompatible with new versions of Visual Studio. – KitsuneYMG Jul 20 '09 at 15:54
  • +1 for also pointing out the error-prone nature of include guards. I've seen them get copied and pasted before without appropriate adjustment - we didn't notice it for years until we tried to include the two headers together in one translation unit and it was a head scratcher given how long it had persisted. I dream of module support, but I'd still be very happy if a #pragma once equivalent became standard. – stinky472 Jul 01 '10 at 08:39
  • 1
    About forward declaring (Another thing that doesn't get mentioned so often): while decreasing compile time, be aware that if you ever want to refactor the forward declared class - e.g. change its name or namespace - all those forward declarations come back at you as you need to change each single one. And they don't even produce clear compiler errors as the forward declaration remains valid. So Ctrl Shift F it is, but boohoo if you declared the same name in a lot of different namespaces... just a side note that forward declarations also have downsides (I do use them still) – Cookie Nov 23 '11 at 15:35
  • 11
    `#pragma once` is not reliable (different file hierarchy perspectives (current-working-directories), soft and hard links, network filesystems, and even name collision --try with a file named `string.h` or something like that--). Not taking into account speed, you could have a script that substituted any, say, `%INCLUDE_GUARD%` in a file for an automatically-managed guard symbol; you would write headers as `header.hpp.in`, and, because you would already have the preprocessor conditional pair, the final header would not flow and the compiler would emit the correct line numbers in diagnostics. – Kalrish Dec 19 '14 at 12:27
  • 1
    I just learned the hard way that `pragma once` is not reliable. (thanks for confirmation, @Kalrish) Header guards did work where `pragma once` didn't. (on MSVC10) I'm now using both. – Brandlingo Apr 20 '15 at 15:13
  • I've never had issues with pragma once, however, I've had issues with include guards. I tried a very basic test: 1. Create two folders, "my" and "your", 2. add the files ifdef.h and pragma.h to both folders, 3. include guard the ifdefs with IFDEF_H and the pragma's with pragma once. 4. define MY_IFDEF, YOUR_IFDEF, MY_PRAGMA, YOUR_PRAGMA, in each respective file in the guarded areas. 5. include all in a test.cpp file. 6. ifdef test for each, cout'ing on exists or non-exists. I found the pragma once defines existed, however one of the ifdef defines did not. When does pragma once fail? – Kit10 Jul 29 '15 at 23:07
  • 46
    I don't understand the alleged reliability problem with `#pragma once`. If I have two different headers `foo/string.h` and `bar/string.h` then putting a `#pragma once` means I'm allowed to include each of them once, but including both of them is also OK. If I use an include guard, then I will probably write something like `#ifndef STRING_H` in both files - which means I can't include both foo/string.h and bar/string.h. – Brandin Aug 26 '15 at 13:38
  • 11
    @Brandin If you have two files both named `string.h`, you're probably going to end up with internal name collisions if you haven't used namespaces anyway as two files with that name are both likely to do something involving strings, and if you use namespaces, in my opinion, you should include the namespace in the include guard identifier. – JAB Nov 06 '15 at 21:54
  • 2
    @Brandin But that's entirely within your control (read: simply don't do that; why would you do that?). Running into reliability problems with `#pragma once` (which are well-documented) may be largely _outside_ of your control. – Lightness Races in Orbit Jul 31 '19 at 13:13
  • @LightnessRacesinOrbit Probably those names were not good examples. You could imagine though a big project with several components, each having a common header with a conventional name e.g. "constants.h", so you end up with comp1/constants.h, comp2/constants.h, .... But each component author won't really be thinking about how her component will be included along with others, so probably she will just write her include guard as #ifdef INCLUDED_CONSTANTS_H or something like that. E.g. the standard way easily leads to an include guard name clash. – Brandin Jul 31 '19 at 14:40
  • @Brian R. Bondy also #pragma once does not do a sanity check so essentially you can create a circular dependency and never even know it, take GLM lib for example type_mat2x2.hpp includes its .inl file, type_mat2x2.inl includes func_matrix.hpp, func_matrix.hpp includes mat2x2.hpp, mat2x2.hpp includes type_mat2x2.hpp, this is 100% a circular dependency because at the end type_mat2x2.hpp is included into itself, however since they use #pragma once instead of include guards, the compiler removed the include and allows the code to function properly allowing a dangerous bug to slip – daniel Aug 18 '19 at 16:32
  • @Brandin you should _never_ have name clashes in your own projects. As JAB points out, namespaces should be used to disambiguate reusable components; alternatively, you can use physical package design (a _requirement_ in Java) to disambiguate. In both cases, systematically including the namespace name or package path in the include guard will eliminate any potential clashes. See [this](https://github.com/bloomberg/bde/wiki/physical-code-organization) article to see a real-world example of physical design and include guards. – Moebius-Rex Sep 01 '19 at 12:51
  • @Moebius Namespaces do not apply to preprocessor symbols e.g. in the above example it is likely that both files would have INCLUDED_CONSTANTS_H or something like that for a traditional include guard, even though they are distinct files. Of course you could disambiguate by naming your symbols more fully, e.g. INCLUDED_COMP1_CONSTANTS_H and INCLUDED_COMP2_CONSTANTS_H but in practice no one does that. – Brandin Sep 01 '19 at 14:05
  • I understand Brandin. I’m suggesting that if you have a package called ABC and a package called DEF, with or without explicit use of the namespace declaration, your include guards could be INCLUDED_ABC_CONSTANTS and INCLUDED_DEF_CONSTANTS to avoid a clash. Also, calling the header files abc_constants.h and def_constants.h improves comprehension and avoids some potentially nasty checkin errors. – Moebius-Rex Sep 01 '19 at 14:10
182

I just wanted to add to this discussion that I am just compiling on VS and GCC, and used to use include guards. I have now switched to #pragma once, and the only reason for me is not performance or portability or standard as I don't really care what is standard as long as VS and GCC support it, and that is that:

#pragma once reduces possibilities for bugs.

It is all too easy to copy and paste a header file to another header file, modify it to suit ones needs, and forget to change the name of the include guard. Once both are included, it takes you a while to track down the error, as the error messages aren't necessarily clear.

Cookie
  • 10,754
  • 13
  • 47
  • 69
  • 2
    This exact thing happened to me and it was beyond frustrating. It took hours to figure out. – chen Mar 27 '19 at 20:11
  • 4
    This is the correct reason. Forget performance—we should use `#pragma once` because it’s less error prone. It occurs to me that if compilers are already tracking include guards, they’re already doing most of the work necessary to issue warnings when they see different files using the same macro name. – rieux Jun 13 '19 at 06:36
146

#pragma once has unfixable bugs. It should never be used.

If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h" and #include "../a/foo.h" refer to the same file, so #pragma once will fail to suppress a redundant include when it should have.

This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization. With #ifndef guards, the compiler can safely read any file it isn't sure it has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers do define the same guard macro, the programmer can go in and change one of them.

#pragma once has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.

(The short version of why this is unfixable is that neither the Unix nor the Windows filesystem API offer any mechanism that guarantees to tell you whether two absolute pathnames refer to the same file. If you are under the impression that inode numbers can be used for that, sorry, you're wrong.)

(Historical note: The only reason I didn't rip #pragma once and #import out of GCC when I had the authority to do so, ~12 years ago, was Apple's system headers relying on them. In retrospect, that shouldn't have stopped me.)

(Since this has now come up twice in the comment thread: The GCC developers did put quite a bit of effort into making #pragma once as reliable as possible; see GCC bug report 11569. However, the implementation in current versions of GCC can still fail under plausible conditions, such as build farms suffering from clock skew. I do not know what any other compiler's implementation is like, but I would not expect anyone to have done better.)

zwol
  • 121,956
  • 33
  • 219
  • 328
  • 39
    On technical level I agree with you, but if the two include guards have the same name, because the files have same name (which is quite likely), there's nothing won. Am I mistaken? – Bim Feb 25 '16 at 12:08
  • 11
    @Bim "If two headers do define the same guard macro, the programmer can go in and change one of them." – zwol Feb 25 '16 at 15:17
  • 58
    FYI this answer [is being discussed on Reddit](https://www.reddit.com/r/cpp/comments/4cjjwe/come_on_guys_put_pragma_once_in_the_standard/d1j04te). People aren’t convinced by your arguments (and I think they have a point). – Konrad Rudolph Mar 30 '16 at 15:51
  • 9
    If the files have the same content, maybe they are the same file? I think this should be good enough, no need to mess with inode numbers or other hacks... – static_rtti Mar 30 '16 at 16:22
  • 3
    @static_rtti Remember that in general C declarations are _not_ idempotent. Including the same file twice, or two files with identical contents, will usually cause compilation to fail. Except when including the same file twice is exactly what the programmer wanted and _not_ doing it will cause compilation to fail. Figuring out which case you're in is probably equivalent to the Halting Problem. – zwol Mar 30 '16 at 16:29
  • 4
    @KonradRudolph I was _wondering_ why it was suddenly attracting more votes. I don't have the time to attempt to persuade people any more than I already have; if they're not convinced, oh well. – zwol Mar 30 '16 at 16:31
  • 9
    "If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. " could you provide a source for this ? – Jean-Michaël Celerier Mar 30 '16 at 17:16
  • @Jean-MichaëlCelerier Unfortunately, I can't tell you more precisely than "dig through the GCC mailing lists and bug tracker circa 2001-2004 for problems with `#import` and/or `#pragma once`." It was a long time ago. – zwol Mar 30 '16 at 17:19
  • 18
    @zwol "Except when including the same file twice is exactly what the programmer wanted and not doing it will cause compilation to fail." That doesn't seem to be a problem to me, because such a file wouldn't have an include guard except in rare edge cases. Such cases could simply be resolved by not using `#pragma once` for that file. – Jordan Melo Mar 30 '16 at 18:38
  • 4
    @JordanMelo I feel like we're in "The compiler cannot tell what you meant it to do" territory here. Don't imagine that you are trying to fix an application that tripped over the bugs I outlined. Instead, imagine you are trying to *implement* `#pragma once`. How do you make it behave reasonably in the face of *arbitrary, unknown, unpredictable in advance* include paths and macro hackery, given only the information available to a compiler, in particular, *not* the contents of the application programmer's mind? – zwol Mar 30 '16 at 19:14
  • 6
    @JordanMelo To put it another way: If you are the compiler programmer you do not get to handwave away "rare edge cases". – zwol Mar 30 '16 at 19:15
  • 10
    @zwol I found this bug report from 2003 : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11569 ; it says at the end : `#pragma once has been undeprecated in 3.4 because it [gcc] contains a correct implementation at last.`. So the damn things works perfectly since about 13 years and yet FUD is still spread ? – Jean-Michaël Celerier Mar 30 '16 at 21:31
  • 7
    @Jean-MichaëlCelerier That refers to https://gcc.gnu.org/ml/gcc-patches/2003-07/msg02780.html in which Neil Booth *thought* he had succeeded in implementing the damn thing correctly, but, reading the code and the subsequent thread, he did *not* address all of the corner cases I was thinking of when I posted this. The most probable failure case is a false negative (file included twice when it should not have been) in the presence of a network file system whose last-modification timestamps are self-inconsistent. – zwol Mar 30 '16 at 21:45
  • 2
    @Jean-MichaëlCelerier (If you don't think a network file system whose last-modification timestamps are self-inconsistent is a scenario worth worrying about, I envy the life you must have lead.) – zwol Mar 30 '16 at 21:47
  • 6
    @zwol `If you don't think a network file system whose last-modification timestamps are self-inconsistent is a scenario worth worrying about, I envy the life you must have lead.` I run into this at work _every day of the week, every single time I compile_. It's not a corner case. If anything the corner case would be that the last-modification timestamps would be consistent when using a network file system. Having said this, I always use `#pragma once`, and never ran into an issue with it. I understand it cannot be implemented reliably, but if you don't do dumb stuff you are ok. – gnzlbg Mar 30 '16 at 23:24
  • 4
    If you have an identical include file, there's no point in including it many times, **iff** it has a `#pragma once` inside of it. This behavior should IMHO be standardized. Implementations using a pair (file size, crypto digest) would be "close enough" I think. The source of the file doesn't matter then: it can be fed over a pipe, over standard input, a web socket, whatever. If the preprocessor reads it as a "file", and it has the pragma, and it's identical to another "file" previously read, it's ignored. Easy peasy. – Kuba hasn't forgotten Monica Apr 04 '16 at 22:01
  • 6
    @KubaOber You have missed the possibility that A/foo.h and B/foo.h might be _textually_ identical, but included (as `#include "foo.h"`), by A/bar.h and B/bar.h respectively, _with different macro definitions in effect_. You might think that this is too farfetched to worry about, but as I said earlier, compiler authors do not get to dismiss anything as too farfetched to worry about. – zwol Apr 04 '16 at 22:15
  • 2
    @KubaOber (I don't even think it's that farfetched, me. I suspect there are bits of the Boost preprocessor library that you use exactly like that.) – zwol Apr 04 '16 at 22:17
  • 21
    @zwol That's OK, if you do it then it shouldn't have `#pragma once` :) Again, one has to define some sort of sane semantics for that pragma. If you want to include the same thing multiple times, don't put the `#pragma once` inside :) – Kuba hasn't forgotten Monica Apr 05 '16 at 13:12
  • 1
    @KubaOber I'm just going to keep repeating "compiler authors do not get to dismiss anything as too farfetched to worry about" until the full implications sink in – zwol Apr 05 '16 at 14:12
  • 19
    @zwol I'm sorry but if A/foo.h and B/foo.h are identical **and** have include guards, then by necessity the include guards are identical too and the second inclusion will still be a ignored no matter what macro definitions are in effect, unless these definitions somehow change the meaning of the include guard (can they? do they?). Boost sources that are meant to be included multiple times for preprocessor "computation" purposes don't have include guards IIRC, it'd be nonsensical for them to have them. So, unless I don't understand you, I don't think it's a real problem. – Kuba hasn't forgotten Monica Apr 05 '16 at 14:18
  • 7
    @KubaOber Please accept for the sake of the hypothetical that there is a header file `foo.h` that *should be* once-only, and that depends on macros defined by the file that includes it. Imagine that this header is copied into two libraries, A and B, which use it differently, and that both libraries are then copied into a larger program. Under either #ifndef guards or your proposed semantic for #pragma once, this will break. **But with #ifndef guards, there is an obvious fix which the person maintaining the larger program can apply without affecting anything else:** change the guard macros. – zwol Apr 05 '16 at 14:27
  • 4
    @KubaOber In contrast, with your proposed semantic for #pragma once, there is also a fix -- change any text in a comment, say -- but it's not obvious from code inspection, the maintainer is going to have to look it up in the manual and then worry about whether that works in all supported compilers. #ifndef guards are therefore a better language feature in terms of user experience. – zwol Apr 05 '16 at 14:29
  • 2
    @zwol So, the workaround is always to modify the file, except that include guards make it more obvious? – Kuba hasn't forgotten Monica Apr 05 '16 at 14:48
  • 2
    @KubaOber Right. But note that this applies only to _your_ semantics for #pragma once. A more pathname-oriented semantic might require you to rename a file in case of a conflict, and that might break an API contract. And compilers have not historically been good at documenting exactly how they implement this stuff, so how would you know what to do? I am thinking about how I might revise my answer to express these things better. – zwol Apr 05 '16 at 15:03
  • 3
    I don't think that there's any way to make pathnames work in a way that's easy to specify and feasible to implement on a random platform. If one were to standardize the behavior of `#pragma once`, the term "path" shouldn't even be mentioned. Include guards don't use paths either, other than the humans usually putting a mangled path there and praying that it doesn't clash with anything. – Kuba hasn't forgotten Monica Apr 05 '16 at 20:39
  • 5
    You described situation where pragma once will fail, but #ifndef also. So what is the point. You have to change content of file. If you use prama once everywhere, you add #ifndef to your files and that's it. If you are using #ifndef everywhere, you change it. If you have specific need for some files #ifndef is what you can use, using pragma once wont disable this possibility. – fbucek Oct 15 '16 at 13:19
  • 3
    @fbucek His point is that "you need to change the file's contents" is more obvious with normal include guards, and depending on how a particular compiler implements it, might not be enough to guarantee success with `#pragma once`. Basically, for include guards, you can tell at a glance that you need to change one of the guards; with `#pragma once`, though, you need to look through the compiler's documentation to see whether you need to change the file's contents, change its name, or what. – Justin Time - Reinstate Monica Feb 15 '17 at 21:57
  • 1
    So, in effect, it's that one has a more obvious fix, and that the logical fix might not actually be enough for the other (depending on the compiler). – Justin Time - Reinstate Monica Feb 15 '17 at 21:58
  • 7
    I never had problems with #pragma once. I only had problems with #ifndef. Usually when I rename file and then create new with automatically generated #ifndef. which is already there, because I did rename file, not the safety guards. Ok #pragma once has bug, which is really rare I think. And it is solvable by modifying file. Just like problems with #ifndef. I still cannot see the point why not to use them. Nothing is 100% perfect. – fbucek Feb 16 '17 at 09:29
  • 4
    GCC fixed the filename approach with correct symlink handing 13 years before this "answer" was posted. Even without filenames or inodes, it's still trivially fixed by using checksums. EDIT: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11569 – MickLH Apr 07 '17 at 20:27
  • @MickLH I refer you to my response to Jean-Michaël Celerier well upthread. They *thought* they fixed it, but they did not. – zwol Apr 08 '17 at 01:45
  • 7
    Any solution based on filenames is an inherently useless waste of time, no further discussion of any filename or path based solutions is necessary. Now, A checksum of the file will not only be consistent across network drives with clock skew, but will even be consistent between duplicates with entirely different names and paths. This correctly implements the only sane use of `#pragma once`, which is to organize data structure definitions using redundant include trees. Calling this an "unfixable bug" is biased or naive, and the "arbitrary unpredictable" paths roadblock is a red herring. – MickLH Apr 08 '17 at 05:09
  • @MickLH Checksums are not an option, as they will break real-world existing uses of the pragma that expect more pathname-like semantics. I also reiterate that as the compiler author you do _not_ get to declare your customers' existing codebases "not sane", no matter how insane you think they are. – zwol Apr 08 '17 at 14:17
  • 5
    That premise is a fallacy! Ok, "not sane" is an opinion and so you absolutely *do* get to declare anyone's codebase as sane or not. The "once" pragma is not rigidly standardized, and so technically an arbitrary choice is valid. As you said above: You could have ripped it out entirely years ago, definitely breaking *many* more codebases than just switching to checksums. This question explicitly asks about mitigating redundant includes, a common and useful task in programming, not obscure abuses of "once" that, as you said, should have been broken and re-written more robustly a long time ago. – MickLH Apr 08 '17 at 18:32
  • @MickLH You are welcome to get in your time machine and go back to 2002 and have an argument with my then-boss about whether the customers' code needs to be supported. – zwol Apr 09 '17 at 13:23
  • 2
    Why can't inode numbers be used? The combination of inode and device number is unique for every file on the system. – fuz Jul 25 '17 at 06:31
  • @fuz Sadly, that is not true; you cannot count on inode _or_ device numbers remaining stable over a filesystem dismount and remount (and yes, that can happen in the middle of a compilation run). – zwol Jul 25 '17 at 11:56
  • 6
    @zwol If you remount files system during compilation, behaviour is undefined, just as behaviour is undefined if you change any files during compilation. That's not really a problem. – fuz Jul 25 '17 at 13:01
  • @fuz Like I said to MickLH, you are welcome to get in your time machine and go back to 2002 and have an argument with my then-boss about whether the customers' code needs to be supported, except s/code/build farm/. – zwol Jul 25 '17 at 16:04
  • 2
    zwol I read the whole thread you linked and don't see any problems ? all the issues that were seen were ultimately fixed. – Jean-Michaël Celerier Jan 24 '18 at 11:34
  • @Jean-MichaëlCelerier I already covered that in both the answer and the comments above. – zwol Jan 24 '18 at 13:11
  • @zwol If you worked on gcc, I trust you and I'm taking your advice, thank you. (Looking forward to new C++ "modules" which I expect will make these concerns mute :-) ) – Coder Jul 10 '18 at 06:24
  • "As long as no two headers define the same guard macro..." is an unfixable bug. – Daniel Stevens Feb 27 '19 at 07:55
  • @DanielStevens If two headers define the same guard macro, one of the macros can be renamed without affecting anything else. If two headers have a name conflict of the type that causes `#pragma once` to get confused, and you insist on continuing to use `#pragma once`, you have to rename one of the headers, which is probably an API break and therefore not possible. – zwol Feb 27 '19 at 14:56
  • That misses the point. Macro names globally affect a compilation unit, even if headers come from separate individually developed libraries, written by separate authors. There is no way for the library writers to reasonably coordinate such a rename, forcing the change onto users of the library. Having to make source code modifications to 3rd party libraries greatly increases the maintenance burden of using those libraries. Neither header guards nor `#pragma once` are a proper module system. – Daniel Stevens Feb 28 '19 at 10:06
  • 1
    @DanielStevens Yes, neither of these things are a proper module system, but I think you overstate the difficulty of keeping header guard macro names from conflicting with each other, or with names used for other purposes. I've encountered such conflicts ... twice in 20 years, if I remember correctly, and neither involved third-party library headers. `#pragma once` malfunctions, on the other hand, were an ongoing problem for my entire tenure at the job with the build farm with the unreliable clocks (see above). – zwol Feb 28 '19 at 13:14
40

Until the day #pragma once becomes standard (that's not currently a priority for the future standards), I suggest you use it AND use guards, this way:

#ifndef BLAH_H
#define BLAH_H
#pragma once

// ...

#endif

The reasons are :

  • #pragma once is not standard, so it is possible that some compiler don't provide the functionality. That said, all major compiler supports it. If a compiler don't know it, at least it will be ignored.
  • As there is no standard behavior for #pragma once, you shouldn't assume that the behavior will be the same on all compiler. The guards will ensure at least that the basic assumption is the same for all compilers that at least implement the needed preprocessor instructions for guards.
  • On most compilers, #pragma once will speed up compilation (of one cpp) because the compiler will not reopen the file containing this instruction. So having it in a file might help, or not, depending on the compiler. I heard g++ can do the same optimization when guards are detected but it have to be confirmed.

Using the two together you get the best of each compiler for this.

Now, if you don't have some automatic script to generate the guards, it might be more convenient to just use #pragma once. Just know what that means for portable code. (I'm using VAssistX to generate the guards and pragma once quickly)

You should almost always think your code in a portable way (because you don't know what the future is made of) but if you really think that it's not meant to be compiled with another compiler (code for very specific embedded hardware for example) then you should just check your compiler documentation about #pragma once to know what you're really doing.

Cache Staheli
  • 2,897
  • 6
  • 30
  • 41
Klaim
  • 60,771
  • 31
  • 121
  • 186
  • 7
    Who said that #pragma once is ever going to be standard? Also, how many compilers don't track if the header file is completely surrounded in include guards? In otherwords - has anybody measured if #pragma once actually makes a difference in reality? – Richard Corden Jul 20 '09 at 08:08
  • 4
    @Richard, I have, and it does in cases - our project had 5500 includes with about 1/2 redundant. – Sam Harwell Jul 20 '09 at 08:49
  • 1
    @Richard Yes performace have been tested by many people, the optimisation is at least present in VC and gcc. I didn't say that #pragma once will be standart, it's just a very big possibility as the standardisation process often consist of standardizing common feature/usage that are proven to be efficient, like #pragma once. – Klaim Jul 20 '09 at 11:19
  • 2
    @280Z28: Obviuosly a complete rebuild of 5500 includes with 50% being redundant is going to cost something. However, can you provide numbers, ie. using the pragma once compilation time (clean if you like) versus not using it. If you reach more than 1% of your total compliation time for a completely clean build I would be shocked. – Richard Corden Jul 20 '09 at 14:01
  • 1
    @Klaim: What you said was - "Until #pragma once becomes standard". The until there implies that it is going to happen but it is just a matter of time. However, C++ '0x has been in the works now for quite some time, and there have been discussions on the usual news groups about the standardisation of the feature. The conclusion was that an existing mechanism exists and so there was no need to add an alternative way of doing the same thing. – Richard Corden Jul 20 '09 at 14:08
  • 1
    @Klaim, 280Z28: Regarding performance, check out the following: http://gamesfromwithin.com/?p=32. Do either of you have numbers for a real project that show complete compile times for the project with and without #pragma once? – Richard Corden Jul 20 '09 at 14:13
  • @Richard - I'll fix the "until" problem as it seem to not be obvious, I just wanted to say that if it's standardized one day, then it will not be necessary to use the guards. For the performance numbers, I don't have some for my current home projects, but we did some after changing some company source code to use pragma once. The compilers were VC9/9 and CodeWarrior. I don't have the exact member but we had somethink like 10% speed compilation improvement. I'm not sure this is interesting, I think we can find numbers on the web or make some test yes, I'll try if I find enough time. – Klaim Jul 20 '09 at 15:33
  • 1
    By the way, the link you provide seems correct because the tests were made on "old" compiler, old enough to not have (Ithink) the optimizations we're talking about. A new test with recent compilers (vc8/9, last g++) would be a good thing indeed, to be sure about that. I agree that we should provide numbers, I don't have some right now. – Klaim Jul 20 '09 at 15:36
  • 1
    "The until there implies that it is going to happen but it is just a matter of time" -- No it doesn't. This is a case of faux pedantry; someone pretending expertise who not only lacks it but hasn't applied even a minimal amount of thought or effort. And I will believe this until he shows up on my doorstep and proves me wrong. – Jim Balter Dec 06 '13 at 22:01
  • 2
    What is the reason for having `#pragma once` *after* the include guard? – DarioP Jul 14 '14 at 14:06
  • 7
    @DarioP: Compilers that recognize it don't care. Compilers that don't recognize it are at risk of disabling include guard optimization when there's stuff outside the include guard. And compilers without optimization will skip everything inside the guard on repeated includes, so less processing involved for what's inside. – Ben Voigt Sep 12 '14 at 16:44
  • 7
    Microsoft seems to have optimized their compiler. From Microsoft's VS2015 documentation: "There is no advantage to use of both the #include guard idiom and #pragma once in the same file. The compiler recognizes the #include guard idiom and implements the multiple include optimization the same way as the #pragma once directive if no non-comment code or preprocessor directive comes before or after the standard form of the idiom" https://msdn.microsoft.com/en-us/library/4141z1cx.aspx – cgmb Apr 08 '17 at 01:25
  • 5
    The "#pragma once" here will never been properly evaluated so is redundant because the guard will always override it. Don't bother, just use the old fashioned guard or only pragma once on a simpler project. – hookenz Jun 21 '17 at 04:18
36

From a software tester's perspective

#pragma once is shorter than an include guard, less error prone, supported by most compilers, and some say that it compiles faster (which is not true [any longer]).

But I still suggest you go with standard #ifndef include guards.

Why #ifndef?

Consider a contrived class hierarchy like this where each of the classes A, B, and C lives inside its own file:

a.h

#ifndef A_H
#define A_H

class A {
public:
  // some virtual functions
};

#endif

b.h

#ifndef B_H
#define B_H

#include "a.h"

class B : public A {
public:
  // some functions
};

#endif

c.h

#ifndef C_H
#define C_H

#include "b.h"

class C : public B {
public:
  // some functions
};

#endif

Now let's assume you are writing tests for your classes and you need to simulate the behaviour of the really complex class B. One way to do this would be to write a mock class using for example google mock and put it inside a directory mocks/b.h. Note, that the class name hasn't changed but it's only stored inside a different directory. But what's most important is that the include guard is named exactly the same as in the original file b.h.

mocks/b.h

#ifndef B_H
#define B_H

#include "a.h"
#include "gmock/gmock.h"

class B : public A {
public:
  // some mocks functions
  MOCK_METHOD0(SomeMethod, void());
};

#endif

What's the benefit?

With this approach you can mock the behaviour of class B without touching the original class or telling C about it. All you have to do is put the directory mocks/ in the include path of your complier.

Why can't this be done with #pragma once?

If you would have used #pragma once, you would get a name clash because it cannot protect you from defining the class B twice, once the original one and once the mocked version.

Konrad Kleine
  • 3,720
  • 3
  • 23
  • 31
  • 6
    This is not practical for any large project. Keep B up2date will be pain and not to mention this violates the One Definition Rule – parapura rajkumar Jul 04 '15 at 12:32
  • 5
    @parapurarajkumar The ODR is not violated because if your include mocks/b.h before b.h the preprocessor will skip b.h entirely leaving you with only one class B. I wonder if you have a less "painful" approach for testing class B. What strategy do you propose for testing "any large project"? – Konrad Kleine Jul 06 '15 at 08:37
  • But there will be other parts of the system i.e. non test code where you can not override gmock.h ? – parapura rajkumar Jul 08 '15 at 00:01
  • 3
    Nobody is overriding "gmock.h". It is part of the Testframework with which we want to simulate a class. I think we're talking about two different things. The whole point is to take existing code or a class hierarchy and as a test replace one part of the chain with a simulator or mocking class. This way you are effectively testing non-testing code. It is not like a unit test where you only test one class on its own but what mocking allows you to do is system testing. And if your class hierarchy uses classical #ifndef include guards you can replace a class with a mock just in your test. – Konrad Kleine Jul 08 '15 at 08:05
  • 2
    Hmm, if both the original `b.h` and the mock `b.h` are in the compiler include paths - won't there be a name clash with `#include "b.h"`? If you remove the original `b.h` path from the include directories for the test project so that only the mock `b.h` is picked up, then won't `#pragma once` also work? – Samaursa Jan 21 '17 at 08:36
  • @Samaursa These are all headers, we have not seen how they are included in compiled code. I would imagine the real cpp would `#include "c.h"`, while the test code would do something like `#include "mocks/b.h"` then `#include "c.h"` or maybe the real code does `#include ` then `#include ` where include path order matters. `c.h` would still include local `b.h` and not `mocks/b.h` because of "" and not <>. But I might be wrong. – Steven Spark Jan 24 '17 at 22:18
  • You also can't do this when using `#pragma once` by add code like `namespace mock_b {#include "b.h"}` in your mocks/b.h. Since the including is pre-process, which ignores `namespace`, it prevents a.h to include b.h and puts real class B in a different namespace without name clash with mock Class B – RolandXu Jul 20 '17 at 02:29
  • 4
    IMO if you're adding `mocks/b.h` to the include path, you should also remove the original `b.h` instead of depending the include guards. Your solution is just as lame as symbol interposition :-/ – Navin Sep 15 '17 at 05:45
  • If C++ was a neighborhood, it would be the worst place to walk through. There's always danger when you least expect it. Just when you thought you mapped out all the tough areas to avoid, out jumps the little guy, #include, to kick you. You never suspected him because he doesn't even live in C++ and was friendly all along. – ATL_DEV Aug 19 '20 at 21:43
25

If you're positive that you will never use this code in a compiler that doesn't support it (Windows/VS, GCC, and Clang are examples of compilers that do support it), then you can certainly use #pragma once without worries.

You can also just use both (see example below), so that you get portability and compilation speedup on compatible systems

#pragma once
#ifndef _HEADER_H_
#define _HEADER_H_

...

#endif
whoKnows
  • 909
  • 1
  • 9
  • 26
Donnie DeBoer
  • 2,377
  • 14
  • 14
  • 28
    #pragma once is well supported over many different compilers including GCC – Brian R. Bondy Jul 17 '09 at 15:29
  • 6
    true, but it's not ubiquitously supported. Include guards are always supported... depends on how portable you want your code to be. – Donnie DeBoer Jul 17 '09 at 15:31
  • 6
    I really don't want both, that just makes the code ugly. As long as portability isn't an issue I think code hygiene issues are next. – Matt Price Jul 17 '09 at 15:33
  • 6
    Portability isn't that much of a deal even if you did care about it. If you're currently writing for Windows-only, there are likely to be other things in your code that tie you more tightly to Windows than #pragma once. And if the day should ever come you do port some of the code, it wouldn't be hard to write a Perl script that went through your headers and replaced all uses of #pragma once with an include guard based on the file name and path. – Steve Jessop Jul 17 '09 at 17:45
  • 3
    On the other hand, if part of the project is writing bits which may eventually be usable elsewhere (e.g. math library, api wrapper, etc) go for portability. You're worrying waaay too much about how your code should LOOK and not about how it should WORK.... especially at the top of a file which people have learned to ignore anyway. – Sean Jul 17 '09 at 18:51
  • @onebyone: The only benefit to using #pragma once from the start is a potential performance boost. There would have to be a significant performance improvement to ever really want to move away from the "standard" way of protecting against multiple inclusions of a header. Clarity should come before performance by default - and in this case even the performance benefit is up for debate. – Richard Corden Jul 20 '09 at 08:52
  • 1
    Identifiers starting with an underscore are reserved to the implementation; don't define them in your own code. – Keith Thompson Sep 16 '13 at 18:06
  • 1
    @KeithThompson "Identifiers starting with an underscore are reserved to the implementation" -- that's too broad. Non-global identifiers may start with an underscore if not followed by a capital letter or another underscore. – Jim Balter Dec 06 '13 at 22:08
  • 1
    @JimBalter: I was admittedly simplifying a bit -- but IMHO it's easier and wiser to follow the more general rule and *never* define identifiers starting with an underscore than to keep track of when you can get away with it. – Keith Thompson Dec 06 '13 at 22:24
  • 1
    @KeithThompson This Q has a C++ tag and a common convention in C++ is for instance variables to start with _ so the overbroad claim could lead one to erroneously believe that these violate the standard. Anyway, I wasn't talking about practices, just the facts of what the standard says. – Jim Balter Dec 07 '13 at 00:08
  • For what it is worth -- Oracle Solaris Studio 12.3 ("Sun Pro C") doesn't support #pragma once. I don't recall getting a warning, but I definitely got compiler errors. :( – PatrickB Mar 09 '16 at 15:33
  • @JimBalter Both ISO C and ISO C++ render such use **undefined behavior** within the standard library clauses (and in recent working draft of C++ this rule was lifted for the whole language as a "shall not be used" with "no diagnostic is required" statement, which is mentally same to UB). It is never a correct practice to use these reserved identifier unless you do know what you are doing (e.g. you're writing an implementation for the standard library). – FrankHB Mar 31 '16 at 02:15
  • @FrankHB names of variables aren't "behavior", so you should cite some text from the standards for such a nonsense claim. And, as I said, starting instance variables with an underscore is a widespread practice, and the standards committees would not be so nuts as to invalidate it. And your reference to "these reserved identifier" suggests that you didn't even read what I wrote, which was about " Non-global identifiers may start with an underscore if not followed by a capital letter or another underscore", which are not and never have been reserved ... "non-global" is a big clue. – Jim Balter Mar 31 '16 at 02:47
  • 1
    @JimBalter True, names aren't behavior, which is "external appearance or action" specified by ISO C11 3.4. However, this is nothing to do allowing use of names. See ISO C11 7.3 and ISO C++14 17.6.4.3, also [the working paper of ISO C++](http://www.eel.is/c++draft/lex.name#3). And "widespread" is irrelevant with "correct". Any serious projects will avoid such use unless it can get guaranteed predicable behavior by other way (e.g. extensions on the language standard like POSIX). Note, for **_ + UPPERCASE, "global" is irrelevant**. Further, macro names are similar to be "global". – FrankHB Apr 04 '16 at 03:15
  • JimBalter, I was talking about the use in this answer. The statement of @KeithThompson was not precise (technically, it was wrong, but misconception based on the statement is less harmful); I'd admit I did not read about it very carefully then. But your statement of "the facts of what the standard says" in this sense is also not correct, regardless with that imprecise statement, until you recited that "not followed by a capital letter or another underscore". Also note **this condition is precedent than "global"**. With this consensus I think we don't have disagreement any longer. – FrankHB Apr 04 '16 at 03:39
  • " I'd admit I did not read about it very carefully then" -- indeed, and you continue in the vein. "until you recited that" -- it's what I said in the first place. "we don't have disagreement any longer" -- your disagreement was with a strawman of your own construction. "widespread" is irrelevant with "correct" -- that's the autistic view, but in the real world, standards committees (I was on X3J11 myself) take pains that widespread usages, such as `_membername`, remain correct. Now I've wasted more than enough time on this chitchat about a 3 year old comment, and won't engage further. – Jim Balter Apr 04 '16 at 04:50
25

After engaging in an extended discussion about the supposed performance tradeoff between #pragma once and #ifndef guards vs. the argument of correctness or not (I was taking the side of #pragma once based on some relatively recent indoctrination to that end), I decided to finally test the theory that #pragma once is faster because the compiler doesn't have to try to re-#include a file that had already been included.

For the test, I automatically generated 500 header files with complex interdependencies, and had a .c file that #includes them all. I ran the test three ways, once with just #ifndef, once with just #pragma once, and once with both. I performed the test on a fairly modern system (a 2014 MacBook Pro running OSX, using XCode's bundled Clang, with the internal SSD).

First, the test code:

#include <stdio.h>

//#define IFNDEF_GUARD
//#define PRAGMA_ONCE

int main(void)
{
    int i, j;
    FILE* fp;

    for (i = 0; i < 500; i++) {
        char fname[100];

        snprintf(fname, 100, "include%d.h", i);
        fp = fopen(fname, "w");

#ifdef IFNDEF_GUARD
        fprintf(fp, "#ifndef _INCLUDE%d_H\n#define _INCLUDE%d_H\n", i, i);
#endif
#ifdef PRAGMA_ONCE
        fprintf(fp, "#pragma once\n");
#endif


        for (j = 0; j < i; j++) {
            fprintf(fp, "#include \"include%d.h\"\n", j);
        }

        fprintf(fp, "int foo%d(void) { return %d; }\n", i, i);

#ifdef IFNDEF_GUARD
        fprintf(fp, "#endif\n");
#endif

        fclose(fp);
    }

    fp = fopen("main.c", "w");
    for (int i = 0; i < 100; i++) {
        fprintf(fp, "#include \"include%d.h\"\n", i);
    }
    fprintf(fp, "int main(void){int n;");
    for (int i = 0; i < 100; i++) {
        fprintf(fp, "n += foo%d();\n", i);
    }
    fprintf(fp, "return n;}");
    fclose(fp);
    return 0;
}

And now, my various test runs:

folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.164s
user    0m0.105s
sys 0m0.041s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.140s
user    0m0.097s
sys 0m0.018s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.193s
user    0m0.143s
sys 0m0.024s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.153s
user    0m0.101s
sys 0m0.031s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.170s
user    0m0.109s
sys 0m0.033s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.155s
user    0m0.105s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.153s
user    0m0.101s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.181s
user    0m0.133s
sys 0m0.020s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.167s
user    0m0.119s
sys 0m0.021s
folio[~/Desktop/pragma] fluffy$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin17.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

As you can see, the versions with #pragma once were indeed slightly faster to preprocess than the #ifndef-only one, but the difference was quite negligible, and would be far overshadowed by the amount of time that actually building and linking the code would take. Perhaps with a large enough codebase it might actually lead to a difference in build times of a few seconds, but between modern compilers being able to optimize #ifndef guards, the fact that OSes have good disk caches, and the increasing speeds of storage technology, it seems that the performance argument is moot, at least on a typical developer system in this day and age. Older and more exotic build environments (e.g. headers hosted on a network share, building from tape, etc.) may change the equation somewhat but in those circumstances it seems more useful to simply make a less fragile build environment in the first place.

The fact of the matter is, #ifndef is standardized with standard behavior whereas #pragma once is not, and #ifndef also handles weird filesystem and search path corner cases whereas #pragma once can get very confused by certain things, leading to incorrect behavior which the programmer has no control over. The main problem with #ifndef is programmers choosing bad names for their guards (with name collisions and so on) and even then it's quite possible for the consumer of an API to override those poor names using #undef - not a perfect solution, perhaps, but it's possible, whereas #pragma once has no recourse if the compiler is erroneously culling an #include.

Thus, even though #pragma once is demonstrably (slightly) faster, I don't agree that this in and of itself is a reason to use it over #ifndef guards.

EDIT: Thanks to feedback from @LightnessRacesInOrbit I've increased the number of header files and changed the test to only run the preprocessor step, eliminating whatever small amount of time was being added in by the compile and link process (which was trivial before and nonexistent now). As expected, the differential is about the same.

fluffy
  • 4,460
  • 28
  • 58
  • "Negligible"? You cut your build time in half. – Lightness Races in Orbit Jul 13 '17 at 01:28
  • @LightnessRacesinOrbit I cut my build time by 0.04 seconds. Which happens to be half, on a source file that's a pathological manifestation of incredibly convoluted `#include` rules, that would likely never appear in real life. The point was to measure how much overhead `#ifndef` guards applied over `#pragma once` and any codebase where that's more than 0.04 seconds has bigger problems. – fluffy Jul 13 '17 at 01:52
  • 6
    Your answer provides insufficient context to tell whether the savings will remain a constant 0.04 seconds as the project grows, or will remain a constant 50% as the project grows, or some place in between. As such, it's not a terribly useful benchmark and the "negligible" conclusion is currently unsupported. I'm only mentioning it because I would be very interested in the real conclusion! – Lightness Races in Orbit Jul 13 '17 at 11:23
  • 1
    That's a good point - it only measures the speed of include guards and not the rest of the preprocessor. I figured it was obvious that the generated code was only testing that aspect given that there isn't a whole lot between the guard lines. Perhaps I could extend the generated code such that each file has a few thousand randomly generated template functions and classes, which makes for a different unrealistic synthetic test. – fluffy Jul 14 '17 at 14:17
  • 1
    Not even just the preprocessor - you're doing a full compilation & link. We just have no way of knowing from these results what the "unrelated constant overhead" is, and therefore the results don't really tell us anything of practical use. Sadly! – Lightness Races in Orbit Jul 14 '17 at 14:30
  • 1
    @LightnessRacesinOrbit I've changed the test to have more #include files and to only run the preprocessor. The time differential is, unsurprisingly, about the same (and is now a much smaller fraction). – fluffy Jul 15 '17 at 20:35
15

I generally don't bother with #pragma once as my code sometimes does have to compile with something other than MSVC or GCC (compilers for embedded systems don't always have the #pragma).

So I have to use #include guards anyway. I could also use #pragma once as some answers suggest, but there doesn't seem to be much reason and it will often cause needless warnings on the compilers that don't support it.

I'm not sure what time savings the pragma might bring. I've heard that compilers generally already recognize when a header has nothing but comments outside of the guard macros and will do the #pragma once equivalent in that case (ie., never processing the file again). But I'm not sure if it's true or just a case of compilers could do this optimization.

In either case, it's just easier for me to use #include guards which will work everywhere and not worry about it further.

Michael Burr
  • 311,791
  • 49
  • 497
  • 724
  • 7
    I'm curious which compiler doesn't support it. It appears most compilers do and I don't know of one which doesn't. – Shital Shah May 20 '16 at 05:58
14

There's an related question to which I answered:

#pragma once does have one drawback (other than being non-standard) and that is if you have the same file in different locations (we have this because our build system copies files around) then the compiler will think these are different files.

I'm adding the answer here too in case someone stumbles over this question and not the other.

Community
  • 1
  • 1
Motti
  • 99,411
  • 44
  • 178
  • 249
9

I think the first thing you should do is check to see if this is really going to make a difference, ie. you should first test the performance. One of the searches in google threw up this.

In the results page, the columns are sligthly off for me, but it's clear that at least up to VC6 microsoft was not implementing the include guard optimisations that the other tools were using. Where the include guard was internal it took 50 times as long compared with where the include guard was external (external include guards are at least as good as #pragma). But let's consider the possible affect of this:

According to the tables presented, the time to open the include and check it is 50 times that of a #pragma equivalent. But the actual time to do so was measured at 1 microsecond per file back in 1999!

So, how many duplicate headers will a single TU have? This depends on your style, but if we say that an average TU has 100 duplicates then in 1999 we're potentially paying 100 microseconds per TU. With HDD improvements this is probably significantly lower by now, but even then with precompiled headers and correct dependency tracking the total cumulative cost of this for a project is almost certainly an insigificant part of your build time.

Now, on the flip side, as unlikely as it may be, if you ever move to a compiler that doesn't support #pragma once then consider how much time will it take to update your entire source base to have include guards rather than #pragma?

There is no reason that Microsoft could not implement an include guard optimisation in the same way that GCC and every other compiler does (actually can anybody confirm if their more recent versions implement this?). IMHO, #pragma once does very little other than limit your choice of alternative compiler.

Richard Corden
  • 20,589
  • 6
  • 55
  • 83
  • 7
    Not to be picky, but if you're porting to a non-pragma-once supporting compiler, writing a one off tool to trawl files and replace #pragma once with conventional include guards will probably be trivial in the face of the overall porting process. – Jherico Nov 10 '14 at 22:41
  • 2
    _"actually can anybody confirm if their more recent versions implement this?"_ It's mentioned in the VS2015 docs that it now does implement include guard optimization. https://msdn.microsoft.com/en-us/library/4141z1cx.aspx – cgmb Apr 08 '17 at 01:27
  • 3
    _"consider how much time will it take to update your entire source base to have include guards rather than #pragma?"_ It shouldn't take long. Making that easy is why I wrote [guardonce](https://github.com/cgmb/guardonce). – cgmb Apr 08 '17 at 01:29
4

#pragma once allows the compiler to skip the file completely when it occurs again - instead of parsing the file until it reaches the #include guards.

As such, the semantics are a little different, but they are identical if they are used they way they are intended to be used.

Combining both is probably the safest route to go, as in the worst case (a compiler flagging unknown pragmas as actual errors, not just warnings) you would just to have to remove the #pragma's themselves.

When you limit your platforms to, say "mainstream compilers on the desktop", you could safely omit the #include guards, but I feel uneasy on that, too.

OT: if you have other tips/experiences to share on speeding up builds, I'd be curious.

peterchen
  • 38,919
  • 19
  • 95
  • 176
  • @Peterchen: It's wrong to state that a compiler needs to re-read the file for include guards. The first time the compiler parses the body it can record if the header had correct include guards. It can therefore skip the header if it is #included later. The key difference is that #pragma is not standard and if you ever need to use a compiler which doesn't support it then you're in a world of pain. The worse that can happen with include guards is that performance suffers very slightly. – Richard Corden Jul 20 '09 at 08:06
  • 8
    Not really a world of pain. You could fairly easily write a script that replaced all occurences of #pragma once with include guards. The worst that can happen with include guards isn't performance, its using misspelled #ifdefs or duplicating a file, changing the contents and forgetting to update the #ifdefs. – kibibu Jul 30 '09 at 04:18
1

For those who would like to use #pragma once and include guards together: If you are not using MSVC, then you won't get much optimization from #pragma once.

And you shouldn't put "#pragma once" into a header that supposed to be included multiple times with each inclusion possibly having a different effect.

Here is a detailed discussion with examples about #pragma once usage.

Deqing
  • 11,990
  • 13
  • 74
  • 113
  • 4
    *"And you shouldn't put `#pragma once` into a header that supposed to be included multiple times."* -- It's intended for headers that are included multiple times; that's the whole point. I think what you mean is that it should't be used for headers that are supposed to be included multiple times *with each inclusion possibly having a different effect*. There are few examples of this; `` or `` is one such example (since its behavior depends on whether `NDEBUG` is defined). – Keith Thompson Sep 16 '13 at 18:36
  • Thanks, that's more clear. Updated my answer. – Deqing Sep 17 '13 at 02:49
1

Atop explanation by Konrad Kleine above.

A brief summary:

  • when we use # pragma once it is much of the compiler responsibility, not to allow its inclusion more than once. Which means, after you mention the code-snippet in the file, it is no more your responsibility.

Now, compiler looks, for this code-snippet at the beginning of the file, and skips it from being included (if already included once). This definitely will reduce the compilation-time (on an average and in huge-system). However, in case of mocks/test environment, will make the test-cases implementation difficult, due to circular etc dependencies.

  • Now, when we use the #ifndef XYZ_H for the headers, it is more of the developers responsibility to maintain the dependency of headers. Which means, whenever due to some new header file, there is possibility of the circular dependency, compiler will just flag some "undefined .." error messages at compile time, and it is user to check the logical connection/flow of the entities and rectify the improper includes.

This definitely will add to the compilation time (as needs to rectified and re-run). Also, as it works on the basis of including the file, based on the "XYZ_H" defined-state, and still complains, if not able to get all the definitions.

Therefore, to avoid situations like this, we should use, as;

#pragma once
#ifndef XYZ_H
#define XYZ_H
...
#endif

i.e. the combination of both.

Community
  • 1
  • 1
parasrish
  • 3,084
  • 22
  • 28