Reputation: 13000
Can a #define or similar pre-processor definition be made across all translation units?
Header implementations are useful for really small libraries since all the code can be contained and distributed with a single header with the following structure:
// library.h
void libFunc(); // forward decl
#ifdef IMPLEMENT_LIBRARY
int libState;
volatile int libVolState; // library state exposed to external processes
void libFunc(){
// definition
}
#endif
This structure however requires the user to define IMPLEMENT_LIBRARY
before the header's inclusion in only one of their translation units, meaning it can't be put in the user's header files, and might be a little confusing to someone who isn't wholely familiar with C++'s compilation rules.
If there were a way to define IMPLEMENT_LIBRARY
across all TU, this could be done automatically with
#ifndef IMPLEMENT_LIBRARY
#defineToAllUnits IMPLEMENT_LIBRARY
// library state
// definitions
#endif
Does such a mechanism exist, or is the current single-header system as good as it's gonna get?
Upvotes: 3
Views: 1895
Reputation: 238351
For this use case, you probably should not use macro definition at all. If you want the function to be defined in the TU of library user, you can use an inline function. Inline functions may be defined in more than one TU (as long as the definition is same):
// library.h
inline void libFunc(){
// definition
}
Another approach would be to compile the library separately, and have the user of the library link with it instead of having the definition inside their own TU.
Regarding the question itself
Can a #define or similar pre-processor definition be made across all translation units?
It is OK to #define pre-processor macros in more than one TU:
// a.cpp
#define foo a
// b.cpp
#define foo b
If you want the definitions to match across all TU that define it, you can put the macro definition into a header file, and include that:
// h.hpp
#define foo h
// a.cpp
#include "h.hpp"
// b.cpp
#include "h.hpp"
It is not possible to "inject" definitions from one TU into other TU's, so there is no possible equivalent of "#defineToAllUnits". It is typically possible to "inject" macro definitions from the compiler invocation: gcc a.cpp b.cpp -Dfoo=h
. I don't see this being useful for your use case however.
Upvotes: 3
Reputation: 52294
Some compilation units could very well have been compiled before the one which would contain a #defineToAllUnits
, so that is not possible.
In practice your problem is often solved by using the build system to pass a -DIMPLEMENTAT_LIBRARY
option to compiler (or equivalent syntax). Another possibility, common when trying to achieve a wide portability with several defines, is to have a configuration header like config.h
included everywhere. That header can be autogenerated at configuration time.
You can also avoid infringing the ODR by using inline
functions and variables.
Upvotes: 3