Why isn't #pragma once automatically assumed? Why isn't #pragma once automatically assumed? c c

Why isn't #pragma once automatically assumed?


There are multiple related questions here:

  • Why is #pragma once not automatically enforced?
    Because there are situations in which you want to include files more than once.

  • Why would you want to include a file multiple times?
    Several reasons have been given in other answers (Boost.Preprocessor, X-Macros, including data files). I would like to add a particular example of "avoid code duplication": OpenFOAM encourages a style where #includeing bits and pieces within functions is a common concept. See for example this discussion.

  • Ok, but why is it not the default with an opt-out?
    Because it is not actually specified by the standard. #pragmas are by definition implementation-specific extensions.

  • Why has #pragma once not become a standardized feature yet (as it is widely supported)?
    Because pinning down what is "the same file" in a platform-agnostic way is actually surprisingly hard. See this answer for more information.


You can use #include anywhere in a file, not just at global scope - like, inside a function (and multiple times if needed). Sure, ugly and not good style, but possible and occasionally sensible (depending on the file you include). If #include was only ever a one time thing then that wouldn't work. #include just does dumb text substitution (cut'n'paste) after all, and not everything you include has to be a header file. You might - for example - #include a file containing auto generated data containing the raw data to initialize a std::vector. Like

std::vector<int> data = {#include "my_generated_data.txt"}

And have "my_generated_data.txt" be something generated by the build system during compilation.

Or maybe I'm lazy/silly/stupid and put this in a file (very contrived example):

const noexcept;

and then I do

class foo {    void f1()    #include "stupid.file"    int f2(int)    #include "stupid.file"};

Another, slightly less contrived, example would be a source file where many functions need to use a large amount of types in a namespace, but you don't want to just say using namespace foo; globally since that would polute the global namespace with a lot of other stuff you don't want. So you create a file "foo" containing

using std::vector;using std::array;using std::rotate;... You get the idea ...

And then you do this in your source file

void f1() {#include "foo" // needs "stuff"}void f2() {    // Doesn't need "stuff"}void f3() {#include "foo" // also needs "stuff"}

Note: I'm not advocating doing things like this. But it is possible and done in some codebases and I don't see why it should not be allowed. It does have its uses.

It could also be that the file you include behaves differently depending on the value of certain macros (#defines). So you may want to include the file in multiple locations, after first having changed some value, so you get different behaviour in different parts of your source file.


Including multiple times is usable e.g., with the X-macro technique:

data.inc:

X(ONE)X(TWO)X(THREE)

use_data_inc_twice.c

enum data_e { #define X(V) V,   #include "data.inc"#undef X};char const* data_e__strings[]={#define X(V) [V]=#V,   #include "data.inc"#undef X};

I don't know about any other use.