Anne Quinn
Anne Quinn

Reputation: 13000

Can a define be made across all translation units?

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

Answers (2)

eerorika
eerorika

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

AProgrammer
AProgrammer

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

Related Questions