在 C++20 中,如果一个宏被#undef,然后再次#define,是否被认为是 "active"?

In C++20, is a macro considered "active" if it's #undef'd, then #define'd again?

考虑

#define VER 1
#undef VER
#define VER 2

#if defined(VER) // #1
#error VER is defined 
#endif

[cpp.import]/6:

A macro directive is active at a source location if it has a point of definition in that translation unit preceding the location, and does not have a point of undefinition in that translation unit preceding the location.

我的理解是VER#1#undef VER)之前有一个未定义点,因此不考虑活跃。也就是说,defined(VER) 应扩展为 0,并且 #error 指令不应生效。

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

我的理解有误吗?我错过了什么?

如评论中所述,必须认识到根据 macro difinition from standard 代码中的两个 define 导致 两个不同的宏定义 。这意味着它们可以被视为逻辑上不同的实体。来自标准:

Each #define directive encountered when preprocessing each translation unit in a program results in a distinct macro definition.

因此,由于第一个 VER 与第二个 VER 的宏定义不同,因此表达式 defined(VER) 为真,符合标准。这些宏唯一的共同点是它们的名称,但并没有详尽地定义它们。

让我们看看我是否可以证明这一点。

上面 link 点的段落说:

  1. Each #define directive encountered when preprocessing each translation unit in a program results in a distinct macro definition.

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

5.1 The point of definition of a macro definition within a translation unit is the point at which its #define directive occurs

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

5.2 The point of undefinition of a macro definition within a translation unit is the first point at which a #undef directive naming the macro occurs after its point of definition, [...]

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

因此,#define VER 2的宏定义在测试的位置处于活动状态。在较早的一些时间点,#define VER 1 将被激活。


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

#define X 1
#define X 2
#undef X

/* is X active now ??? */

第一个 #define 似乎没有“未定义点”,但我认为您 运行 会与

发生冲突

7 If a macro would be replaced or redefined, and multiple macro definitions are active for that macro name, the active macro definitions shall all be valid redefinitions of the same macro

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