取消定义并重新定义__cplusplus宏

时间:2018-12-10 14:15:15

标签: c++ macros undef

我想取消定义并重新定义__cplusplus宏,但是编译错误:__cplusplus was not declared in this scope

#define TEMP_VERSION __cplusplus // temporary macro to hold the __cplusplus  containt
#undef __cplusplus
#define __cplusplus TEMP_VERSION  // redefine __cplusplus

#define AA 111
#undef AA
#define AA 111

int main()
{
    cout << "__cplusplus = "<<__cplusplus<<endl; // It doesn't work
    cout << "AA = "<<AA<<endl; // It works

    return 0;
}
  • 问题1:为什么它不能与__cplusplus一起使用,但可以与AA一起使用

我知道这确实很丑陋,但未定义宏的原因是我正在使用第三方软件,其中他们滥用#ifdef __cplusplus,我的意思是#ifdef __cplusplus ... #endif的内容是错误。因此,我没有更改他们的软件,而是选择执行以下

#define TEMP_VERSION __cplusplus
#undef __cplusplus
#include <third_party_sw.h>
#define __cplusplus TEMP_VERSION
  • 问题2:您认为这是一种好方法吗?

3 个答案:

答案 0 :(得分:4)

根据C ++标准([cpp.predefined,3-4]):

  

预定义宏的值(__FILE____LINE__除外)   在整个翻译单元中保持不变。如果有   本节中的预定义宏名称或定义的标识符,   是#define或#undef预处理指令的主题,   行为是不确定的。

换句话说,__cplusplus宏不仅仅是编译器在将控制权移交给您之前通过定义开始的内容;它是一个不变的常量,不能更改,并且是尝试更改的错误。

关于是否可能是一个好的方法:取决于上下文,但可能不是。这种“愚弄标头”的骇客(#define private public,有人吗?)很少有效,也永远都不安全。

编辑:哦,顺便说一句,即使您确实有一个宏,保存/恢复也是合法的,但这并不是正确的方法。参见Can I redefine a C++ macro then define it back?

答案 1 :(得分:1)

这是因为__cplusplus由编译器预先定义。

从技术上讲,定义它们的是预处理器,但是根据哪个编译器调用预处理器,输出可能会有所不同。尝试运行此:

$ g++ -dM -E - </dev/null

输出是所有预处理器定义的(在这种情况下)此命令运行的预处理器产生的结果。

__cplusplus并不在那里。它是每个C ++编译单元内置的。

(将clang++替换为g++时也是如此。)

答案 2 :(得分:1)

  

问题1:为什么它不能与__cplusplus一起使用,但可以与AA一起使用

因为__cplusplus是一个预定义的宏,并且(未定义)它的行为是未定义的:

  

标准草案[cpp.predefined]

     

如果此子节中的任何预定义宏名称或定义的标识符是#define或#undef预处理指令的主题,则该行为是未定义的。 ...

AA不是预定义的宏,标识符也不是保留的。可以(重新)定义它。


  

问题2:您认为这是一种好方法吗?

(重新)定义保留标识符永远不是一个好方法。甚至重新定义用户定义的宏也是一个可疑的命题。

如果可能的话,理想的方法可能是修复第三方软件。另外,您可以为没有问题的软件编写自定义标头。