Including header files in C/C++ more than once [duplicate] Including header files in C/C++ more than once [duplicate] c c

Including header files in C/C++ more than once [duplicate]


Yes, it's useful when generating code with the preprocessor, or doing tricks like Boost.PP does.

For an example, see X Macros. The basic idea is that the file contains the body of the macro and you #define the arguments and then #include it. Here's a contrived example:

macro.xpp

std::cout << MESSAGE;#undef MESSAGE

file.cpp:

int main() {# define MESSAGE "hello world"# include "macro.xpp"}

This also allows you to use #if and friends on the arguments, something that normal macros can't do.


Yes, including a header more than once can be useful (though it is fairly unusual). The canonical example is <assert.h>, which defines asssert differently depending on whether NDEBUG is defined or not. As such, it can make sense to include it, then have a (usually conditional) definition of NDEBUG, followed by including it again, with (at least potentially) different definitions of assert:

The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included1.

Most headers, however, go to some pains to be idempotent (i.e., to have the same effects no matter how often they're included).


1C99, ยง7.2/1.


A typical example (untested) - point being that it factors a list of enumerations so they appear consistently in an enum and in streaming code:

// states.hX(Uninitialised)X(Initialised)X(Running)X(Complete)X(Shutdown)// app.c++#if defined(X)# error X is already defined#endifenum States {    #define X(TAG) TAG,    #include "states.h"    #undef X    Extra_So_Trailing_Comma_Ignored};std::ostream& operator<<(std::ostream& os, const States& state){    #define X(TAG) if (state == TAG) return os << #TAG;    #include "states.h"    #undef X    return os << "<Invalid-State>";}