math.h宏观碰撞

Mik*_*kel 7 c++ glibc g++ c++11

DOMAINmath.h中的宏与枚举和可能的其他类型冲突.我不知道该怎么做.

#include <algorithm>

enum Type { DOMAIN };


int main(){
    Type t = Type::DOMAIN;
    return 0;

}
Run Code Online (Sandbox Code Playgroud)

用标志-std = c ++ 11编译.这段代码的C99版本编译完全正常但:

#include <algorithm>

enum Type { DOMAIN };


int main(){
    Type t = DOMAIN;
    return 0;

}
Run Code Online (Sandbox Code Playgroud)

我检查了源代码,库是责备.算法包括stl_algo.h,其中有ifdef:

#if __cplusplus >= 201103L
#include <random>     // for std::uniform_int_distribution 
#include <functional> // for std::bind
#endif
Run Code Online (Sandbox Code Playgroud)

以下代码在c ++ 11编译器上编译良好:

#include <random>
#include <iostream>
int main(){
    std::cout << DOMAIN << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它是一个功能还是一个bug?

编辑*脏修复:

#ifdef DOMAIN
#undef DOMAIN
#endif
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 7

这是一个错误(如果你想要慷慨,那就是"疣").

本答案的其余部分仅涉及GCC和Gnu标准C库头.该man页面引用到Linux系统(但我已经添加了链接man7.org).

DOMAIN宏观来自math.h的System V的支持.(请参阅man matherr.)系统V支持通常通过定义_SVID_SOURCE功能测试宏(请参阅参考资料)来启用man feature_test_macros,但如果_GNU_SOURCE已定义,则启用它以及大量其他扩展,如果未定义任何功能测试宏,则默认启用.

gcc_GNU_SOURCE如果--std省略或设置为选项,则预定义C程序gnu##.--std=c##导致__STRICT_ANSI__定义各种选项.因此,使用一些显式C标准编译C代码将抑制System V扩展.这需要完成,因为System V扩展不是标准兼容的,甚至不是Posix,因为它们会污染全局命名空间.(DOMAIN这只是这种污染的一个例子.)

但是,即使指定了g++定义,因此系统V扩展也会潜入.(感谢@dyp提供此libstdc ++ FAQ条目的链接.以及2001年GCC邮件列表上的这个长期且不确定的讨论)_GNU_SOURCE--std=c++##

一个丑陋的解决方法是自己设置功能,然后取消定义__USE_SVID:

#include <features.h>
#undef __USE_SVID

#include <random>
#include <iostream>

int main(){   
    std::cout << DOMAIN << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(住在coliru)

恕我直言,这不应该是必要的.但它确实如此.