C++预处理器 #define-ing 关键字。是否符合标准?
帮助解决评论中正在进行的争论 这个关于 bool 和 1 的问题:
符合标准的 C++ 预处理器是否允许使用 #define
重新定义语言关键字?如果是这样,符合标准的 C++ 预处理器是否必须允许这样做?
如果一个 C++ 程序重新定义了一个语言关键字,那么该程序本身是否符合标准?
Help settle the debate that's going on in the comments at this question about bool and 1:
Can a standards-conforming C++ preprocessor allow one to use #define
to redefine a language keyword? If so, must a standards-conforming C++ preprocessor allow this?
If a C++ program redefines a language keyword, can that program itself be standards conforming?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 C++ 中,与禁止 #define 关键字最接近的是 §17.4.3.1.1/2,它仅在包含标准库头的翻译单元中禁止使用该关键字:
该段落的第二句已在 C++0x 中更改为完全禁止#define
关键字(C++0x FCD §17.6.3.3.1):编辑: 正如 Ken Bloom 在 对其答案的评论,C++0x中的规则没有改变;文本刚刚被重新排列,以迷惑像我这样的人。 :-)
In C++, the closest thing to forbidding
#define
ing a keyword is §17.4.3.1.1/2, which only disallows it in a translation unit that includes a standard library header:The second sentence of that paragraph has been changed in C++0x to outright forbid#define
ing a keyword (C++0x FCD §17.6.3.3.1):Edit: As pointed out by Ken Bloom in comments to his answer, the rules have not changed in C++0x; the text has just been rearranged to confuse people like me. :-)
根据 C++11 [macro.names],这是不允许的:
“表3中列出的标识符”是
final
和override
;属性标记是[[fallthrough]]
中的标识符,依此类推。最新标准中也仍然存在该条款。
It is not permitted, according to C++11 [macro.names]:
The "identifiers listed in Table 3" are
final
andoverride
; and the attribute-tokens are the identifiers in[[fallthrough]]
and so on.This clause is still in the latest standard too.
根据 2005-10-19 C++ 工作草案进行工作 (因为我没有方便的标准):
第 16.3 节将
#define
的语法定义为#defineidentifier replacement-list-newline
(对象-类宏)或以#defineidentifier lparen
开头的几种结构之一(类函数宏)。identifier
在第 2.10 节中定义为identifier-nondigit |标识符 非数字 | 标识符标识符数字
。第 2.11 节指出,在编译的第 7 阶段(第 2.1 节)中,某些标识符被无条件地视为关键字,因此我得出的结论是,它们因此在第 4 阶段(即预处理器扩展)中没有被特殊对待。 因此,该标准似乎要求预处理器允许您重新定义语言关键字(第 2.11 节中列出)。然而,预处理器有一个自己的关键字,即
define
,以及预定义宏的列表(第16.8节)。第 16.8 节指出,如果重新定义它们,则行为是未定义的,但并不禁止预处理器将它们识别为宏名称。Working from the 2005-10-19 C++ working draft (since I don't have a standard handy):
Section 16.3 defines the grammar for
#define
to be#define identifier replacement-list-newline
(object-like macros) or one of several constructions beginning with#define identifier lparen
(function-like macros).identifier
s are defined in section 2.10 to beidentifier-nondigit | identifier identifier-nondigit | identifier digit
. Section 2.11 indicates that a certain list of identifiers are unconditionally treated as keywords in phase 7 of compilation (section 2.1), and I conclude that they are therefore not treated specially in phase 4, which is preprocessor expansion. Thus, it appears that the standard requires the preprocessor to allow you to redefine language keywords (listed in Section 2.11).However, the preprocessor has a keyword of its own, namely
defined
, as well as a list of predefined macros (Section 16.8). Section 16.8 states that the behavior is undefined if you redefine these, but does not prohibit the preprocessor from recognizing these as macro names.