Home > Net >  Use of #error directive in include guards
Use of #error directive in include guards

Time:02-16

I have just stumbled upon a project in which the include guards of every header file look like this:

#ifndef A_H
#define A_H

/* Code */

#else
#error "Multiple inclusion of file a.h"
#endif

Is there an actual usecase for having an #error directive there? It looks like it kills the purpose of having an include guard at all.

The code compiles and works perfectly when removing the #else-#error directives.

CodePudding user response:

Is there an actual usecase for having an #error directive there?

Possibly. But it's not typical.

It looks like it kills the purpose of having an include guard at all.

Indeed. Having the error directive makes the include guard redundant.

CodePudding user response:

Is there an actual usecase for having an #error directive there?

Yes. I created such headers for my project.

My goal was to create a header that defines macros, and another header that undefines them.

For example:

define.h:

#ifndef DEFINE_H
#define DEFINE_H
    // We can now include undef.h
    #undef UNDEF_H
    #define FWD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
    
    #define EXPR(...) \
        noexcept(noexcept(__VA_ARGS__)) \
        -> decltype(__VA_ARGS__) { \
            return __VA_ARGS__; \
        }
    
    #define LIFT(func) [&](auto&&... args) EXPR(func(FWD(args)...))
#else
    #error "A previous header leaked the macros"
#endif

undef.h:

#ifndef UNDEF_H
    // Can include define.h again
    #undef DEFINE_H

    // Have to include define.h to include undef again
    #define UNDEF_H

    // Undef macros
    #undef FWD
    #undef EXPR
    #undef LIFT
#else
    #error "Undef must be paired with define"
#endif

That way, you must include define before your code (after all other includes) and include undef.h at the end of the header file, and they always have to be paired.

It looks like it kills the purpose of having an include guard at all.

Depends on how you want to protect your headers. If that a.h is only meant to be included by that project (as a private header) and the project has a specific location that includes it, it should not be a problem if all other include guards are correct.

For example: b.h

#ifndef B_H
#define B_H
#include "a.h"
#endif

If you include b.h multiple time, a.h is only included one time and no errors occurs.

  • Related