MYSQL头文件与C++的STL<algorithm>冲突

3
// File test.cpp
#include <my_global.h>
#include <algorithm>
int main()
{
    return 0;
}

使用以下命令编译:g++ -c -I /usr/local/mysql/include/mysql/ test.cpp,其中 /usr/local/mysql 是 mysql 的安装目录。然后编译器会报告以下错误:

从 /usr/include/c++/4.4/algorithm:61 中包含文件,从test.cpp:3开始: 在 /usr/include/c++/4.4/bits/stl_algobase.h:232中,错误:宏“min”传递了3个参数,但只使用了2个。 在 /usr/include/c++/4.4/bits/stl_algobase.h:253中,错误:宏“max”传递了3个参数,但只使用了2个。 从 /usr/include/c++/4.4/bits/stl_algo.h:61中包含文件,从/usr/include/c++/4.4/algorithm:62开始,从test.cpp:3开始: 在 /usr/include/c++/4.4/bits/algorithmfwd.h:353中,错误:宏“max”传递了3个参数,但只使用了2个。 在 /usr/include/c++/4.4/bits/algorithmfwd.h:364中,错误:宏“min”传递了3个参数,但只使用了2个。 从 /usr/include/c++/4.4/algorithm:61中包含文件,从test.cpp:3开始: 在 /usr/include/c++/4.4/bits/stl_algobase.h:186中,错误:在常量之前期望未限定的标识符。 在 /usr/include/c++/4.4/bits/stl_algobase.h:186中,错误:在常量之前期望“)”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:186中,错误:在常量之前期望“)”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:186中,错误:在常量之前期望初始化程序。 在 /usr/include/c++/4.4/bits/stl_algobase.h:209中,错误:在常量之前期望未限定的标识符。 在 /usr/include/c++/4.4/bits/stl_algobase.h:209中,错误:在常量之前期望“)”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:209中,错误:在常量之前期望“)”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:209中,错误:在常量之前期望初始化程序。 在 /usr/include/c++/4.4/bits/stl_algobase.h:232中,错误:“std :: min”声明为内联变量。 在 /usr/include/c++/4.4/bits/stl_algobase.h:232中,错误:template declaration of 'const _Tp& std::min'。 在 /usr/include/c++/4.4/bits/stl_algobase.h:235中,错误:期望主表达式之前的内容“if”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:235中,错误:期望在“if”之前的“}”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:237中,错误:在未限定的标识符之前期望声明“return”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:253中,错误:“max”声明为内联变量。 在 /usr/include/c++/4.4/bits/stl_algobase.h:253中,错误:template declaration of 'const _Tp& max'。 在 /usr/include/c++/4.4/bits/stl_algobase.h:256中,错误:期望主表达式之前的内容“if”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:256中,错误:期望在“if”之前的“}”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:258中,错误:在未限定的标识符之前期望声明“return”。 在 /usr/include/c++/4.4/bits/stl_algobase.h:259中,错误:在'}'标记之前期望声明。

我认为在my_global.h和algorithm之间存在名称冲突,因此我将my_global.h放入了一个命名空间中:

// File test.cpp
namespace MYSQL_NAMESPACE {
    #include <my_global.h>
}
#include <algorithm>
int main()
{
    return 0;
}

但是这并没有帮助,编译器仍然报告相同的错误。然后我按照以下顺序更改了包含顺序:
// File test.cpp
#include <algorithm>
#include <my_global.h>
int main()
{
    return 0;
}

现在一切都很顺利。

有人真的知道问题是什么吗?

谢谢!


你正在使用哪个版本的MySQL? - Mark Byers
1
通常情况下,您应该先包含标准的 C 头文件,然后是标准的 C++ 头文件,最后再包含第三方库。 (值得一提的是,windows.h 也有这个问题 - 您可以使用宏 NOMINMAX 关闭 minmax 的定义) - Billy ONeal
我使用的MySQL版本是5.1.44,我现在知道问题所在了,谢谢! - zJay
@Billy ONeal,虽然这是一个好习惯,但仅仅改变包含顺序为“C头文件”>“std头文件”>“第三方库”并不能完全解决这个问题。例如,文件“util1.h”包含<algorithm>,而文件“util2.h”包含<my_global.h>,现在“test.cpp”同时包含“util1.h”和“util2.h”,它们都是“test.cpp”的第三方库,所以第三方库的包含顺序也会影响编译结果。关闭“min”和“max”的定义可能是解决方案。 - zJay
是的,当涉及到宏时,有时候无法处理这些事情。 - Billy ONeal
Boost和MySQL-C也都定义了一个名为“test”的宏。#undef技巧同样适用于它们。 - Móż
3个回答

8

看起来mysql头文件定义了一个宏min

#if !defined(max)
#define max(a, b)       ((a) > (b) ? (a) : (b))
#define min(a, b)       ((a) < (b) ? (a) : (b))
#endif

这已经被报告给 MySQL 作为 Bug 28184。该 Bug 被标记为已关闭,所以请尝试更新到最新版本。根据 Bug 页面的说明,该问题应在版本 5.1.23、6.0.4 及更高版本中得到解决。


7
这就是宏不好的原因之一。 - Fred Larson

3

显然,命名空间技巧不起作用,因为min/max是宏,预处理器不会查看命名空间范围。

这可能会解决问题:

#include <my_global.h>
#undef min
#undef max
#include <algorithm>

整个事情看起来很糟糕 :)

这个立即生效,向Boost和MySQL报告命名不当的宏有时会最终起作用。 - Móż

0

看起来 my_global.h 定义了一些被 algorithm 用作预处理器宏的名称,导致编译失败。使用可行的顺序,您将无法使用 my_global.h 篡改的任何内容,但是除非您需要该功能,否则您的代码至少会编译。由于预处理器宏没有命名空间,因此命名空间包装不起作用,正如您所观察到的那样。

因此,听起来像是 my_global.h 出了问题,但如果一切正常,只需使用可行的包含顺序并继续使用即可。这也是我首选的包含顺序 - 首先是标准库头文件,然后是外部库头文件,最后是内部头文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接