3

I am trying to ban the inclusion of a list of header files from a source file, and thus preventing the dependency on classes defined in those headers.

There are tricks of checking the header guard macros (like the following), but, in my case, the headers to exclude all use #pragma once instead of header guards.

#ifdef A_BANNED_HEADER_FILE_H
static_assert(false);
#endif

Is there a way to enforce 0 inclusion at compile time?

P.S. For the purpose of avoiding dependency to any class, I could define a class of the same qualified name in the source file and let redefinition error scream at accidental inclusion.

9
  • Technically header guards is nothing more than a common convention to prevent multiple inclusion into a single translation unit. As such, the compiler and its preprocessor doesn't really deal with it. Commented Jan 7 at 17:25
  • 2
    This might be a job for a script that runs before the compile command. Commented Jan 7 at 17:28
  • #error seems more appropriate than static_assert(false); BTW Commented Jan 7 at 17:28
  • 1
    This seems like a solution in search of a problem. Commented Jan 7 at 18:43
  • 1
    @PeteBecker, this is an actual situation my team is in. We need to enforce some Clean Code coding guidelines to new code that we add in an existing code base where we cannot change other teams' code. We try to use interfaces instead of directly calling other teams' mockless APIs so we can unit test our core logic. However, the code base's build system cannot prevent undesired header inclusion. We need to find a way to prevent undesired dependency from creeping in. Commented Jan 7 at 23:24

1 Answer 1

4

Preventing a header from being included doesn't necessarily prevent any class from being defined.

But you can explicitly demand that a class is not defined in your source file.

// foo.h must not be included, because class foo must not be defined!
// #include "foo.h"


template<typename T> concept is_defined = requires { sizeof(T); };


static_assert( !is_defined<class foo> );

See it work in Compiler Explorer

Note that you don't want the same concept to evaluate differently in the same program, so it's important to avoid any code that expects a different result for is_defined<class foo>

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

5 Comments

Nice trick using the concept. I assume this will also work for free function dependency.
Don't we have ODR violation if is_defined<foo> is true in one TU and not in another one?
@Jarod42 this is the closest I can come to an answer. There are rules to determine if a concept is satisfied, and it is IFNDR if this result changes within a program. I take this to mean that there should be no code evaluating is_defined<class foo> to have a different result (making this answer okay). I don't think hypothetical changes to satisfaction would be ill-formed or very many concepts would break.
I meant, if another TU does (and expect) static_assert(is_defined<class foo>);, we are in troubles. Incomplete types are dangerous with concept...
@Jarod42 we seem to be on the same page then. I'll add a note to this answer.

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.