C ++预处理器#define-ing a keyword。 标准是否符合标准?

C++ preprocessor #define-ing a keyword. Is it standards conforming?

在这个关于bool和1的问题的评论中帮助解决正在进行的辩论:

符合标准的C ++预处理器是否允许使用#define重新定义语言关键字? 如果是这样,符合标准的C ++预处理器是否允许这样做?

如果C ++程序重新定义了一个语言关键字,那么该程序本身是否符合标准?


在C ++中,最接近禁止#define关键字的是§17.4.3.1.1/ 2,它只允许在包含标准库头的翻译单元中使用它:

A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.

该段落的第二句在C ++ 0x中被改为彻底禁止#define一个关键字(C ++ 0xFCD§17.6.3.3.1):

A translation unit shall not #define or #undef names lexically identical to keywords.

编辑:正如Ken Bloom在回答他的回答中指出的那样,规则在C ++ 0x中没有改变;文本刚刚被重新排列,以迷惑像我这样的人。 :-)


从2005-10-19 C ++工作草案开始工作(因为我没有标准的方便):

第16.3节将#define的语法定义为#define identifier replacement-list-newline(类似对象的宏)或以#define identifier lparen开头的几种结构之一(类似函数的宏)。 identifier在2.10节中定义为identifier-nondigit | identifier identifier-nondigit | identifier digit。第2.11节表明在编译的第7阶段(第2.1节)中无条件地将某个标识符列表视为关键字,因此我得出结论,因此在第4阶段(即预处理器扩展)中不对它们进行特殊处理。因此,标准似乎要求预处理器允许您重新定义语言关键字(在第2.11节中列出)。

但是,预处理器有一个自己的关键字,即defined,以及一个预定义宏列表(第16.8节)。第16.8节声明如果重新定义这些行为,则行为是未定义的,但不禁止预处理器将这些行为识别为宏名称。


根据C ++ 11 [macro.names],这是不允许的:

A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.

"表3中列出的标识符"是finaloverride;和属性标记是[[fallthrough]]中的标识符,依此类推。

该条款仍然是最新的标准。