QT 类型被外部库定义为 int?

QT Type being defined as an int by an external library?

我正在将一个项目集成到另一个项目中,但在使用 QT 时遇到了一些构建问题。 我遇到的问题是在声明 QMetaType::Bool 的 moc 文件中生成的一行。 它说“expected unqualified-id before 'int'”,后面跟着由那个错误引起的一对括号错误。 根据我的研究,其他人说这是由于 xlib.h 在项目的其他地方将 Bool 定义为 int。 我试过“#undef Bool”行,但它似乎不起作用。当我将它放在调用堆栈中最新的 cpp 文件的 header 中时,上面提到的错误消失了,但它也打破了我在所述 cpp 文件中声明的所有 objects,给我我知道一堆未定义的参考错误是不正确的。 那么两个问题:

  1. 尽管我显式调用了 QMetaType:: 命名空间,但为什么我会收到一个错误,它从不同的库中获取不同的 Bool 定义?

  2. 有没有其他方法可以解决这个问题?

编辑:这是导致 moc 文件中问题的功能块。

#undef QT_MOC_LITERAL

static const uint qt_meta_data_FUNCTIONNAMEREDACTED[] = {

 // content:
       7,       // revision
       0,       // classname
       0,    0, // classinfo
       6,   14, // methods
       0,    0, // properties
       0,    0, // enums/sets
       0,    0, // constructors
       0,       // flags
       0,       // signalCount

 // slots: name, argc, parameters, tag, flags
       1,    0,   44,    2, 0x0a /* Public */,
       3,    1,   45,    2, 0x0a /* Public */,
       5,    1,   48,    2, 0x0a /* Public */,
       6,    0,   51,    2, 0x0a /* Public */,
       7,    1,   52,    2, 0x0a /* Public */,
       9,    1,   55,    2, 0x0a /* Public */,

 // slots: parameters
    QMetaType::Void,
    QMetaType::Void, QMetaType::Int,    4,
    QMetaType::Void, QMetaType::Int,    4,
    QMetaType::Void,
    QMetaType::Void, QMetaType::Bool,    8,
    QMetaType::Void, QMetaType::QString,   10,

       0        // eod
};

C++中的C preprocessor是对C的继承

粗略地说,它提供了超出(之前)编译器精确语法分析的文本替换。 (cppreference.com – Phases of translation)

因此,预处理器是 namespace 不可知论者,这在 C 中不是问题(名称空间之类的东西根本不存在),但它可能会在 C++ 中造成奇怪的影响。

虽然我第一次听说 xlib.h 的问题,但这是有关 windows.h 的常见奇怪问题的来源(它广泛使用宏在 ASCII 和 Unicode 风格之间切换API 个函数)。

预处理的中间结果通常直接输入到以下编译器阶段,这样作者就不会立即看到意外的替换。

然而,每个 C 和 C++ 编译器都提供了一个 preprocessor-only 运行 选项,它发出生成的 C 或 C++ 源代码。因此,如果出现奇怪的 hard-to-explain 错误,例如 OP 中的错误,可能值得至少访问发生错误的 C++ 源代码的预处理源文件。

(即使header文件报错,也必须追溯到源文件,因为#include也是预处理对象。)

这些预处理文件可能会变得非常大,因为许多标准 and/or 系统 header 也可能(间接)包含在内,导致单个 C++ 源文件有数千行。

另一个选项是启用有关包含的 headers 的诊断输出。

对于 MSVC++,resp。选项是 /showIncludes。默认情况下通常禁用此选项,因为即使仅列出包含项也常常会导致冗长且不便的诊断输出。


一旦某个宏(直接或间接包含在 header 中定义)被确定为麻烦源,就可以考虑如何 work-around 这个问题了。

主要有两种选择:

  1. 更改 #includes
  2. 的顺序
  3. #undef 相应的。在相关 #include 之后或至少在该源文件中的最后一个 #include 之后的宏。

这必须在每个相关的 C++ 源文件中完成。

它也可以在 header 中完成,但这很容易出错,我不推荐这样做。原因很简单:

宏可能已定义、未定义、再次定义,实际执行方式取决于确切的顺序,文件由编译器“看到”。 对于 C++ 源文件,这很清楚,因为它本身就是一个 translation unit。 相反,header 可能包含在其他 header 之前或之后的不同位置,这在 header 本身编写时很难预测。