Ken*_*oom 20 c++ c-preprocessor
在这个关于bool和1的问题的评论中帮助解决正在进行的辩论:
符合标准的C++预处理器是否允许#define用户重新定义语言关键字?如果是这样,符合标准的C++预处理器是否允许这样做?
如果C++程序重新定义了一个语言关键字,那么该程序本身是否符合标准?
Jam*_*lis 23
在C++中,最接近禁止#define关键字的是§17.4.3.1.1/ 2,它只允许在包含标准库头的翻译单元中使用它:
包含标头的转换单元不应包含定义在该标头中声明或定义的名称的任何宏.这样的翻译单元也不应该为与关键字词汇相同的名称定义宏.
该段的第二句已在C++ 0x中更改为彻底禁止#define关键字(C++ 0xFCD§17.6.3.3.1):
翻译单元不得#define或#undef名称与关键字词汇相同.
编辑: 正如Ken Bloom在回答他的回答中指出的那样,规则在C++ 0x中没有改变; 文本刚刚被重新排列,以迷惑像我这样的人.:-)
根据 C++11 [macro.names],这是不允许的:
翻译单元不应
#define使用与#undef关键字、表 3 中列出的标识符或 7.6 中描述的属性标记在词法上相同的名称。
“表 3 中列出的标识符”是final和override;属性标记是[[fallthrough]]等等中的标识符。
最新标准中也仍然存在该条款。
从2005-10-19 C++工作草案开始工作(因为我没有标准的方便):
第16.3节定义了文法#define是#define identifier replacement-list-newline(类似对象的宏)或开头几种结构中的一个#define identifier lparen(函数宏).identifiers在第2.10节中定义为identifier-nondigit | identifier identifier-nondigit | identifier digit.第2.11节表明在编译的第7阶段(第2.1节)中无条件地将某个标识符列表视为关键字,因此我得出结论,因此在第4阶段(即预处理器扩展)中不对它们进行特殊处理.因此,标准似乎要求预处理器允许您重新定义语言关键字(在第2.11节中列出).
但是,预处理器有一个自己的关键字,即defined一个预定义的宏列表(第16.8节).第16.8节声明如果重新定义这些行为,则行为未定义,但不禁止预处理器将这些行为识别为宏名称.