1

我想取消定义并重新定义 __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:为什么它不能__cplusplusAA

我知道这真的很难看,但我取消定义宏的原因是我正在使用第三方软件,他们在使用错误的#ifdef __cplusplus,我的意思是 的内容#ifdef __cplusplus ... #endif是错误的。因此,我没有更改他们的软件,而是选择执行以下操作

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

3 回答 3

5

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

__FILE__预定义宏的值(和除外__LINE__)在整个翻译单元中保持不变。如果本子条款中的任何预定义宏名称或定义的标识符是#define 或#undef 预处理指令的主题,则行为未定义。

换句话说,__cplusplus宏不仅仅是编译器在将控制权交给您之前通过定义开始的东西;它是一个不可变的常数,无法更改,尝试更改是错误的。

至于如果可能的话,这是否是一个好方法:取决于上下文,但可能不是。这些类型的“愚弄标题”黑客(#define private public,有人吗?)很少有效,而且从不安全。

编辑:哦,顺便说一句,即使您确实有一个宏,保存/恢复也是合法的,但这不是正确的方法。请参阅我可以重新定义 C++ 宏然后重新定义它吗?.

于 2018-12-10T14:26:20.130 回答
1

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

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

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

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

请注意,您__cplusplus不会出现在那里。它内置于每个 C++ 编译单元。

(替换时同样有效clang++g++

于 2018-12-10T14:21:14.350 回答
1

问题 1:为什么它不适用于 __cplusplus 但适用于 AA

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

标准草案 [cpp.predefined]

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

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


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

(重新)定义保留标识符从来都不是一个好方法。甚至重新定义用户定义的宏也是一个可疑的提议。

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

于 2018-12-10T15:02:56.383 回答