是否可以在所有翻译单元中定义#define或类似的预处理程序定义?
标头实现对于非常小的库很有用,因为所有代码都可以包含和分发为具有以下结构的单个标头:
// library.h
void libFunc(); // forward decl
#ifdef IMPLEMENT_LIBRARY
int libState;
volatile int libVolState; // library state exposed to external processes
void libFunc(){
// definition
}
#endif
但是,此结构要求用户在将标头仅包含在他们的翻译单元之一之前定义IMPLEMENT_LIBRARY
,这意味着它不能放入用户的标头文件中,并且可能会使某些人感到困惑对C ++的编译规则并不完全熟悉。
如果有一种方法可以在所有TU上定义IMPLEMENT_LIBRARY
,则可以使用以下方法自动完成
#ifndef IMPLEMENT_LIBRARY
#defineToAllUnits IMPLEMENT_LIBRARY
// library state
// definitions
#endif
这种机制是否存在,或者当前的单头系统是否会达到最佳状态?
答案 0 :(得分:2)
对于此用例,您可能根本不应该使用宏定义。如果要在库用户的TU中定义函数,则可以使用内联函数。内联函数可以在一个以上的TU中定义(只要定义相同):
// library.h
inline void libFunc(){
// definition
}
另一种方法是分别编译库,并让库的用户与其链接,而不是将定义包含在自己的TU中。
关于问题本身
是否可以在所有翻译单元中定义#define或类似的预处理程序定义?
可以在多个TU中#define预处理程序宏:
// a.cpp
#define foo a
// b.cpp
#define foo b
如果要使定义与定义它的所有TU匹配,则可以将宏定义放入头文件中,并包括以下内容:
// h.hpp
#define foo h
// a.cpp
#include "h.hpp"
// b.cpp
#include "h.hpp"
不可能将一个TU的定义“注入”到其他TU,因此不可能有等效的“ #defineToAllUnits”。 通常可以从编译器调用gcc a.cpp b.cpp -Dfoo=h
中“注入”宏定义。但是,我认为这对您的用例没有帮助。
答案 1 :(得分:2)
有些编译单元很可能已经在包含#defineToAllUnits
的单元之前被编译了,所以这是不可能的。
在实践中,通常可以通过使用构建系统将-DIMPLEMENTAT_LIBRARY
选项传递给编译器(或等效语法)来解决您的问题。尝试通过多个定义实现广泛的可移植性时,另一种常见的可能性是在每个地方都包含config.h
这样的配置头。该标头可以在配置时自动生成。
您还可以通过使用inline
函数和变量来避免侵犯ODR。