代码之家  ›  专栏  ›  技术社区  ›  cpplearner

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

  •  0
  • cpplearner  · 技术社区  · 3 年前

    考虑一下

    #define VER 1
    #undef VER
    #define VER 2
    
    #if defined(VER) // #1
    #error VER is defined 
    #endif
    

    [cpp.import]/6 :

    宏观指令是 积极的 如果源位置在该位置之前的翻译单元中有一个定义点,并且在该位置之后的翻译单元里没有一个未定义点。

    我的理解是 VER 有a 未定义点 前面的 #1 (the #undef VER ),因此不考虑 积极的 也就是说, defined(VER) 应扩展到 0 ,以及 #error 指令不应生效。

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

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

    0 回复  |  直到 3 年前
        1
  •  6
  •   ilkkachu    3 年前

    让我们看看我能不能为这件事辩护。

    上面链接点的段落说:

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

    所以, #define VER 1 这是一个定义,以及 #define VER 2 是一个独特的。

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

    显然,两者都有定义。

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

    还有 #定义VER 1 具有不确定性,而 #定义VER 2 不。

    因此,宏观定义 #定义VER 2 在测试位置处于活动状态。在一些较早的点上, #定义VER 1 相反,它将是活跃的。


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

    #define X 1
    #define X 2
    #undef X
    
    /* is X active now ??? */
    

    第一个似乎没有“定义点” #define ,但我认为你会触犯

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

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

        2
  •  1
  •   bartop    3 年前

    正如评论中提到的,人们必须意识到,根据 macro difinition from standard 两个 define 代码中的s结果为 两个不同的宏观定义 这意味着它们可以被视为逻辑上不同的实体。根据标准:

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

    所以,自从第一次 VER 宏定义与第二个不同 版本 ,表达 defined(VER) 符合标准。这些宏的唯一共同点是它们的名称,但它并没有详尽地定义它们。