0

I'm looking for a way to enforce that certain headers cannot be included into the same file.

To explain the situation further, assume I have the headers

a_1.h, b_1.h

and

a_2.h, b_2.h

I want to prevent the inclusion of _1 and _2 files into the same file, regardless of if they were

a_ or b_
7
  • 9
    Put the include guards for _2 into the _1 files, and vice versa. Commented Feb 4, 2019 at 16:58
  • 11
    While I agree with the above comment, I would also point out the fact, that the design requiring this is probably a bad design. Commented Feb 4, 2019 at 17:01
  • @govind Where would it be defined though? I can't do so from the files themselves and I don't want this to be something passed via the command line. Commented Feb 4, 2019 at 17:02
  • 1
    The point that it will not tell you that you have messed up. But the compiler will tell you if it finds redefined symbols. So better not to have such a guard. Commented Feb 4, 2019 at 17:09
  • 2
    Create a new header, ab.h, that correctly includes the right pair of files, and only ever include that in your other source code. The separate a_1.h .. b_2.h files are then used only by the one header. Further, this can be extended to handle a_3.h and b_3.h if necessary(next year? this year?). If there are source files that only work with a_1.h (and not with a_2.h or any of the b_*.h files), so be it. You'll be doing conditional builds for those source files anyway (but consider whether ab.c that conditionally includes a_1.c and b_1.c (or a_2.c and b_2.c) would work. Commented Feb 4, 2019 at 17:43

2 Answers 2

6

Assuming that mixing the _1 and _2 headers is a mistake that needs to be caught, a simple way of catching it is to define and check guard macros to check for mixed usage of these headers and use the #error directive to report errors.

For example, the a_1.h header can include this code:

#ifndef A_1_H__INCLUDED
#define A_1_H__INCLUDED

/* Define header set as 1 if not already defined. */
#ifndef HEADER_SET
#define HEADER_SET 1
#endif

/* Check for consistent header set usage. */
#if HEADER_SET != 1
#error "Inconsistent header sets"
#endif

/* Other header stuff ... */

#endif /* A_1_H__INCLUDED */

The other headers will be similar but the _2 headers will have #define HEADER_SET 2 and #if HEADER_SET != 2.

Sign up to request clarification or add additional context in comments.

9 Comments

I may be missing something, but why introduce another macro instead of checking for the presence of the other include guard?
@StoryTeller Because there may be several other guard macros for a_2.h, b_2.h. etc.
I don't find the need to assign a unique number to each one to be that much better. Still a synchronization nightmare.
@StoryTeller It's a unique number for each incompatible set of header files, not for each individual header file.
@StoryTeller So suggest your own answer.
|
1

Remember that ANY other file in the build process can include a header. With the typical include guard: #ifndef MYHEADER \n #include MYHEADER, the header code is only inserted on the first instance. After that, the compiler has eaten it and remembers and doesn't need to include it again. Think of compiling as putting ALL the source code into one file and turning that into a binary. (you know, "compiling" as in putting it all in a pile). So it's not "into the same file" it's "into the same build".

You want a header file to be mutually exclusive with another header file. (Like, say, if you've got code that targets specific hardware via includes, and you obviously can't build towards two chips at the same time.) First off, if that's an issue, you should really have a single place where such things are defined (like the build script) so that's not a problem. But if you want a simple safeguard:

#ifndef PPC_e6500
#define PPC_e6500
#ifdef LINUX
#error This processor ain't big enough for the both of us, Tux. This here's 8548 territory!
#endif

That will fail to build and you can figure out who did whatever horrible thing that tried to build towards two targets at once.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.