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,给我我知道一堆未定义的参考错误是不正确的。
那么两个问题:
尽管我显式调用了 QMetaType:: 命名空间,但为什么我会收到一个错误,它从不同的库中获取不同的 Bool 定义?
有没有其他方法可以解决这个问题?
编辑:这是导致 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 这个问题了。
主要有两种选择:
- 更改
#include
s 的顺序
#undef
相应的。在相关 #include
之后或至少在该源文件中的最后一个 #include
之后的宏。
这必须在每个相关的 C++ 源文件中完成。
它也可以在 header 中完成,但这很容易出错,我不推荐这样做。原因很简单:
宏可能已定义、未定义、再次定义,实际执行方式取决于确切的顺序,文件由编译器“看到”。
对于 C++ 源文件,这很清楚,因为它本身就是一个 translation unit。
相反,header 可能包含在其他 header 之前或之后的不同位置,这在 header 本身编写时很难预测。
我正在将一个项目集成到另一个项目中,但在使用 QT 时遇到了一些构建问题。 我遇到的问题是在声明 QMetaType::Bool 的 moc 文件中生成的一行。 它说“expected unqualified-id before 'int'”,后面跟着由那个错误引起的一对括号错误。 根据我的研究,其他人说这是由于 xlib.h 在项目的其他地方将 Bool 定义为 int。 我试过“#undef Bool”行,但它似乎不起作用。当我将它放在调用堆栈中最新的 cpp 文件的 header 中时,上面提到的错误消失了,但它也打破了我在所述 cpp 文件中声明的所有 objects,给我我知道一堆未定义的参考错误是不正确的。 那么两个问题:
尽管我显式调用了 QMetaType:: 命名空间,但为什么我会收到一个错误,它从不同的库中获取不同的 Bool 定义?
有没有其他方法可以解决这个问题?
编辑:这是导致 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 这个问题了。
主要有两种选择:
- 更改
#include
s 的顺序
#undef
相应的。在相关#include
之后或至少在该源文件中的最后一个#include
之后的宏。
这必须在每个相关的 C++ 源文件中完成。
它也可以在 header 中完成,但这很容易出错,我不推荐这样做。原因很简单:
宏可能已定义、未定义、再次定义,实际执行方式取决于确切的顺序,文件由编译器“看到”。 对于 C++ 源文件,这很清楚,因为它本身就是一个 translation unit。 相反,header 可能包含在其他 header 之前或之后的不同位置,这在 header 本身编写时很难预测。