4 ms·
I very rarely encounter #pragma once in the wild personally, and I still always use old school #ifndef guards myself. I can't really see a reason to change: it'
by simias 6y ago
I very rarely encounter #pragma once in the wild personally, and I still always use old school #ifndef guards myself. I can't really see a reason to change: it's not a huge amount of typing, it works everywhere, it's very explicit and not magical.
For instance out of the top of my head I don't remember how #pragma once decides what constitutes the same include file. If you have symbolic links, or absolute and relative paths for instance, how does it work? I'm sure I can find the answer in the compiler's documentation, but with #ifndef I don't even have to, it's obvious what's going to happen.
I would personally argue that old school guards should be preferred because of this and the fact that they're standard, but I don't feel super strongly about it.
- WJW 6y agoWouldn't it be as simple as maintaining a bloom filter containing the absolute paths of every included file encountered so far? Whenever you encounter #pragma once you check if the file is already present in the bloom filter and return early if it is. If it's a new file you add the file name to the bloom filter and continue processing. It probably even more memory efficient (albeit insignificant in the grand scheme of compiler memory usage) for the compiler to just maintain the bloom filter and not have to deal with hundreds of otherwise unused preprocessor symbols, one per include file.
- branko_d 6y agoBloom filter can have false positives.
- somebodynew 6y agoThe typical argument against pragma once is that it's unclear what should happen if two different hard link paths are used to include a file with the same inode (along with similar situations on Windows or with files on network drives). That is to say, in general, there is no consistent and portable "true" absolute path that uniquely identifies file(s) as conceptually having the same underlying storage. In practice, I have never actually seen a problem arise. The most likely real trigger would probably be a mix of including a library through a path that indicates a specific version and including it through a path that uses a "latest stable" link. That is already fragile and asking for trouble, though.
- jstimpfle 6y agoI've seen terrible bugs in the past where there were multiple incompatible versions of a header file in a codebase, but nobody noticed because both headers used the same guard variable name, so the header that was included first always won.
- ncmncm 6y agoYes, this is the usual failure mode. It happens quite often, because nothing checks for unique or correct guard names. Failing to switch to `#pragma once` when it becomes permissible is reckless and irresponsible.
- guenthert 6y agoI'd think it would be much easier for a preprocessor to determine that it is done with a file, once it encounter that pragma, instead of having to scan for the corresponding #endif (not sure if it'll dare to scan from the back and hope that all #if/#ifdef, #endif pairs match or whether it diligently checks those every time).
- ncmncm 6y agoYou may imagine that you are helping the compiler avoid error, but the fact is that real compilers, when they encounter `#include` guards, translate therm implicitly to `#pragma once`, and move on. The compiler is better at it than you are. Meanwhile, you are exposing yourself to subtle bugs resulting from multiple headers that define the same guard name, as noted nearby. So, your imagined virtue is folly.