【问题标题】:Can I mimic a C header that redefines bool in C++?我可以模仿在 C++ 中重新定义 bool 的 C 头文件吗?
【发布时间】:2014-03-24 20:16:21
【问题描述】:

我正在编写一个程序,我更喜欢用 C++ 编写,但是,我需要包含一个重新定义 bool 的 C 头文件:

# define false 0
# define true  1
typedef int bool;

显而易见的解决方案是编辑标题说:

#ifndef __cplusplus
# define false 0
# define true  1
typedef int bool;
#endif

但是,唉,因为图书馆是只读的,我不能。

有没有办法让 gcc 忽略这个 typedef?或者,我可以用 C++ 编写大多数函数,然后为这两个函数制作一个 C 包装器吗?或者,我应该接受它并用 C 写东西吗?

【问题讨论】:

  • 如果那是<stdbool.h>,您可以只使用#define 适当的标签,它必须说它已经完成了它的工作。如果是 C,__bool_true_false_are_defined
  • @chris <stdbool.h> 应该已经有自己的 c++ 守卫了
  • 可能会有一些有用的东西:stackoverflow.com/questions/19377678/…
  • @Erbureth,但你不希望它发生一次。
  • @chris 我的意思是 c++ 守卫,而不是标准包括守卫

标签: c++ c typedef mixing


【解决方案1】:

我想您可以将有问题的代码包装到标头中,然后取消定义您不需要的代码

Library_wrapper.h:

#define bool something_else // This will get you past the C++ compilation
#include "library.h"
#undef false
#undef true
#undef bool

main.cpp:

#include "Library_wrapper.h" 
#include "boost.h"

关于 typedef.. 如果您尝试在 C++ 中重新定义基本类型,编译器应该会报错。你可以顺便重新声明一个类型(在C++中是允许的)或者定义它(简单的文本替换)。

【讨论】:

  • Prolly 有问题的 typedef 而不是 #defines。
  • 在 C++ 中你可以重新定义 typedefs,在 C 中你不能,所以我认为需要上述的解决方法
  • 我评论了您的原始帖子,其中不包括您修改 typedef 的编辑。
  • -1, typedef int int;合法的。你从哪里得到的?这是类型说明符和无声明符的无效组合。它甚至看起来不是一个解决方案,而只是重复了手头的问题,这是同样无效的构造typedef int bool;
  • “在 C++ 中你可以重新定义 typedefs”——你可以重复 typedef 声明,而不是改变其含义。它们表现为声明,而不是定义,类似于两次声明函数原型。 “C you can't”——规则在 C 中是一样的。
【解决方案2】:

很遗憾,不,您不能在标准 C++ 中使用此文件:

§7.1.3 [dcl.typedef]

6/ 在给定范围内,不得使用 typedef 说明符重新定义在该范围内声明的任何类型的名称以引用不同的类型。

因此typedef ... bool;是被禁止的。

§17.6.4.3.1 [macro.names]

2/ 翻译单元不得#define#undef 名称在词法上与关键字、表 3 中列出的标识符或 7.6 中描述的属性标记相同。 p>

§2.12 [lex.key]中我们发现bool是一个关键字。

因此,禁止在包含违规文件之前使用#define bool ... 来欺骗编译器。


那么,有什么选择呢?垫片!

在你自己的 C & C++ 兼容头文件后面隔离那个有问题的库;并将这部分编译为 C。然后您可以在 C++ 程序中包含自己的头文件,而不会出现问题或技巧。

注意:是的,大多数编译器可能会接受#define bool ...,但标准仍然明确禁止。

【讨论】:

  • 注意:我注意到 [macro.names] 显然仅适用于您在翻译单元中包含标准库标头的情况。
【解决方案3】:

您可以编译使用 C 标头的代码,然后将其与您的 C++ 目标文件链接在一起。您可能使用 MSVC 或 GCC;两者都可以将代码编译为 C++ 或 C,并允许您创建兼容的目标文件。

这是一个干净的解决方案还是不必要的过度杀伤真的取决于具体情况。

【讨论】:

    【解决方案4】:

    你可以破解它!

    图书馆,称为fooLib,认为它正在使用某种类型bool,它有定义它的特权。对于图书馆来说,bool 只是一个标识符。

    因此,您可以强制它使用另一个标识符:

    #define bool fooLib_bool
    #include "fooLib.h"
    #undef bool
    #undef true
    #undef false
    

    现在编译器看到有问题的行转换为:

    typedef int fooLib_bool;
    

    您被困在使用类型 fooLib_bool = int 而不是真正的 bool 的界面上,但这无法解决,因为代码实际上可能依赖于 int 的属性,而库二进制文件将具有编译时加入了这样的假设。

    【讨论】:

    • 这可能不是问题,因为库二进制文件无论如何都会看到 int 并且您需要在接口级别提供一个 in(或者 bool 将被强制转换为它)
    • 严格来说,#define <keyword> ... 是被禁止的。我想大多数 C++ 编译器都会接受它,但他们有权拒绝编译程序。
    • @MatthieuM., Only if you include a standard library header. 我不太确定如果宏在那里并且在之前包含任何标头之前全部消失。
    • @chris:我讨厌 C++ 标准。严重地。我从未阅读过任何其他具有如此复杂定义和规则的文档。每次你发现一个硬性规则(终于!)时,它都会被其他地方的一些措辞所缓解。 叹息
    • @MatthieuM.,我可以同意。这当然让它变得有趣。我有一种感觉,它的复杂性可以与我们赖以生存的规律相媲美。
    【解决方案5】:

    您可以复制错误的标题并使用经过编辑的副本。告诉编译器它应该喜欢的路径和...

    【讨论】:

    • 或者,只要确保在 C 库之前包含编辑后的副本,标题保护将负责其余部分。 +1
    • 哦……但请注意,“已修补”标头可能会导致 ABI 与库不兼容。除非以后可以重新编译库,或者不需要编译,否则不应修补标头。
    猜你喜欢
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多