【问题标题】:undefine and redefine the __cplusplus macro取消定义和重新定义 __cplusplus 宏
【发布时间】:2018-12-10 14:15:15
【问题描述】:

我想取消定义并重新定义 __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:您认为这是一种好的方法吗?

【问题讨论】:

  • 以双下划线开头的名称保留用于实现。从技术上讲,这是 UB。
  • 因为 'AA' 被定义为在 '
  • “#ifdef __cplusplus ... #endif 的内容是错误的” 你可能应该询问一个适当的解决方法(给出一些关于什么是错误的细节) , 现在这是一个典型的 XY 问题
  • “它适用于 AA 你使用 AA 的方式不同。考虑:coliru.stacked-crooked.com/a/06065c268a7c2bff

标签: c++ macros undef


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    标准草案 [cpp.predefined]

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

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


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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      (将clang++ 替换为g++ 时同样有效。)

      【讨论】:

      • “请注意__cplusplus 不会出现在那里。它是每个 C++ 编译单元的内置函数。”我认为你错过了一些东西。你的预处理器,尽管被 from g++ 调用,当以这种方式调用时,not 定义 __cplusplus。试试echo __cplusplus | g++ -EP -。与echo __cplusplus&gt;foo.cpp;g++ -EP foo.cpp比较。
      • @HWalters 是的,我写道它没有出现在那里。吹毛求疵肯定是一个很好的爱好,但在这种情况下,这对 OP 没有帮助。
      猜你喜欢
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多