在 C++20 中,如果宏被 #undef'd,然后再次 #define'd,那么它是否被认为是“活动的”?

cpp*_*ner 7 c++ language-lawyer c++20

考虑

#define VER 1
#undef VER
#define VER 2

#if defined(VER) // #1
#error VER is defined 
#endif
Run Code Online (Sandbox Code Playgroud)

[cpp.import]/6 :

如果宏指令在该位置之前的翻译单元中具有定义点,并且在该位置之前的翻译单元中没有未定义点,则该宏指令在源位置处处于活动状态

我的理解是在(the )之前VER有一个undefinition 点,因此它不被认为是active。也就是说,应该扩展到,并且该指令不应该生效。#1#undef VERdefined(VER)0#error

但在实践中,所有编译器都会产生一条错误消息VER is defined(这符合我的直觉,但不符合我对标准的理解)。

我的理解不正确吗?我错过了什么?

ilk*_*chu 6

让我们看看我是否可以为此辩护。

上面链接指向的段落说:

  1. 在对程序中的每个翻译单元进行预处理时遇到的每个 #define 指令都会产生一个不同的宏定义。

所以,#define VER 1是一个定义,而且#define VER 2是一个不同的定义。

5.1 翻译单元中宏定义的定义点是其#define 指令出现的点

显然,两者都有一个定义点。

5.2 翻译单元内宏定义的取消定义点是在其定义点之后出现命名宏的#undef 指令的第一个点,[...]

并且#define VER 1有一个#define VER 2不确定的点,而没有。

因此,宏定义#define VER 2在测试位置是活动的。在某些较早的时间点,#define VER 1将改为活跃。


再说一次,如果你要这样做:

#define X 1
#define X 2
#undef X

/* is X active now ??? */
Run Code Online (Sandbox Code Playgroud)

第一个似乎没有“不确定点” #define,但我认为你会遇到

7 如果一个宏将被替换或重新定义,并且该宏名称有多个激活的宏定义,则激活的宏定义都应是同一宏的有效重新定义

因为它们不是同一个宏。(在cpp.replace页面中有示例。)虽然 GCC 和 Clang 接受了警告,但明显的语义是用新值重新定义它(而不是例如堆叠定义以便#undef只删除一个 - 那样说疯狂。)