【问题标题】:Can a define be made across all translation units?是否可以对所有翻译单元进行定义?
【发布时间】:2020-03-27 02:43:46
【问题描述】:

可以在所有翻译单元中进行#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

是否存在这样的机制,或者当前的单头系统是否达到预期效果?

【问题讨论】:

  • 大多数编译器都支持-D 选项来定义符号
  • @AndyG 我不认为这就是 OP 的意思。该代码应该有条件地为其他翻译单元定义宏。

标签: c++ c-preprocessor translation-unit


【解决方案1】:

某些编译单元很可能在包含#defineToAllUnits 的编译单元之前已经编译,所以这是不可能的。

实际上,您的问题通常通过使用构建系统将-DIMPLEMENTAT_LIBRARY 选项传递给编译器(或等效语法)来解决。在尝试通过多个定义实现广泛的可移植性时,另一种常见的可能性是在任何地方都包含像config.h 这样的配置头。该标头可以在配置时自动生成。

您还可以通过使用inline 函数和变量来避免侵犯 ODR。

【讨论】:

    【解决方案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。但是,我认为这对您的用例没有用。

    【讨论】:

    • 这绝对是可取的,尽管在我的情况下,实现具有无法内联的全局状态;它是一个写入文件的调试库
    • @AnneQuinn 你到底是什么意思? inline 函数实际上与非内联函数相同,除了链接行为。
    • @AnneQuinn,在 C++ 中,内联函数可以有静态局部变量,含义很明显。 (在 C 中,他们不能)。
    • @AProgrammer - 我没想到会这样……真是个奇怪的怪癖。 volatile 会改变那个属性吗?变量本身需要暴露给可以写入它的外部进程。
    • @AnneQuinn,从 C++17 开始,您可以使用内联变量。
    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 2021-12-29
    • 1970-01-01
    相关资源
    最近更新 更多