关于标准:重新定义C++关键字是否合法?

Is it legal to redefine a C++ keyword?

在这篇来自本周古鲁的文章中,有人说:It is illegal to #define a reserved word.这是真的吗?我在标准中找不到任何东西,例如,我已经看到程序员重新定义了新的。


17.4.3.1.1宏名称[lib.macro.name]

1 Each name defined as a macro in a header is reserved to the implementation for any use if the translation unit includes the header.164)
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.

顺便说一下,new是一个运算符,用户可以通过提供自己的版本来超载(替换)。


C++ 11对应的部分:

17.6.4.3.1宏名称[宏名称]

1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
2 A translation unit shall not #define or #undef names lexically identical to keywords.

从C++ 03中删除了第1段。第二段被分成两段。前半部分现在已更改为专门声明它只适用于标准头段。第二点已经扩展到包含任何翻译单元,而不仅仅是包含标题的翻译单元。

但是,本标准本节概述(17.6.4.1[约束条件.概述])规定:

This section describes restrictions on C++ programs that use the facilities of the C++ standard library.

因此,如果你不使用C++标准库,那么你可以做你想做的事情。

因此,在C++ 11的上下文中回答你的问题:如果你使用C++标准库,你不能定义(或不定义)任何翻译单元中与关键字相同的任何名称。


他们实际上是错的,或者至少没有把整个故事讲出来。它被禁止的真正原因是它违反了一个定义规则(顺便提一下,这也是它非法的第二个原因)。

要看到它实际上是被允许的(重新定义关键字),至少如果不使用标准库,您必须查看标准的完全不同的部分,即翻译阶段。它说,输入只在预处理发生之前分解成预处理器令牌,看那些在privatefubar之间没有区别的令牌,它们都是identifiers到预处理器。稍后,当输入分解为token时,替换已经发生。

有人指出,对要使用标准库的程序有限制,但不明显的是,重新定义private的示例是这样做的(与"person 4:语言律师"片段相反,后者使用它来输出到cout)。

上一个例子中提到,技巧不会被其他翻译单位践踏,也不会被其他翻译单位践踏。考虑到这一点,您可能应该考虑到在其他地方使用标准库的可能性,这将使此限制生效。


如果你不想有人使用Goto,你可以做一件事。把下面的代码放到他不会注意到的地方。

1
#define goto { int x = *(int *)0; } goto

现在,每当他试图使用goto语句时,他的程序都会崩溃。


据我所知,这并不是非法的-如果你这样做的话,我遇到的任何编译器都不会产生错误。

1
#define true false

#defining某些关键字可能由于其他原因在编译时产生错误。但其中很多只会导致非常奇怪的程序行为。