重新定义C ++关键字是否合法?
在本周的Guru 这篇文章中 ,有人说:定义It is illegal to #define a reserved word.
这是真的? 我找不到任何规范,例如,我已经看到程序员重新定义新的东西。
17.4.3.1.1macros名称[lib.macro.names]
1如果翻译单元包含标题,则在标题中被定义为macros的每个名字被保留给实施用于任何用途。
2包含标题的翻译单元不得包含任何定义该标题中声明或定义的名称的macros。 这样的翻译单位也不应该定义与关键字词汇相同的名称的macros。
顺便提一下, new
是一个运算符,它可以由用户通过提供自己的版本来重载(replace)。
C ++ 11中的相应部分:
17.6.4.3.1macros名称[macro.names]
1包含标准库头的翻译单元不得在任何标准库头中声明的#define或#undef名称。
2翻译单位不得#define或#undef与关键字词汇相同的名称。
C ++ 03中的第1段已被删除。 第二段已经分成两段。 现在上半部分已经被改为具体说明它只适用于标准头文件。 第二点已扩大到包括任何翻译单位,而不仅仅是包含标题的翻译单位。
但是,标准的这一部分的概述 ( 17.6.4.1 [constraints.overview] )指出:
本节介绍对使用C ++标准库的设施的C ++程序的限制。
因此,如果你不使用C ++标准库,那么你可以做你想做的事情。
因此,要在C ++ 11的环境下回答您的问题:如果您使用的是C ++标准库,则无法定义(或取消定义)与任何翻译单元中的关键字相同的任何名称。
如果你不想让别人使用goto,你可以做一些小事。 只要把他的代码放在他不会注意到的地方。
#define goto { int x = *(int *)0; } goto
现在每次他尝试使用goto语句,他的程序都会崩溃。
他们其实是错的,或者至less不会讲整个故事。 它被拒绝的真正原因是它违反了单一定义规则(顺便提一下,这也是违法的第二个原因)。
要看到它实际上是允许的(重新定义关键字),至less如果你不使用标准库,你必须看看标准的完全不同的部分,即翻译阶段。 它说input只在预处理发生之前被分解为预处理标记,并且看着private
和fubar
之间没有区别,它们都是预处理器的identifiers
。 之后,当input被分解为token
,replace已经发生。
有人指出,使用标准库的程序有一个限制,但重新定义private
的例子并不明显(这与“第四人:语言律师”片段相反输出到cout
)。
在最后一个例子中提到,这个技巧不会被其他翻译单位践踏,也不会被其他翻译单位践踏。 考虑到这一点,你可能应该考虑标准库被其他地方使用的可能性,这将会使这个限制生效。
这不是我所知道的非法 – 没有我遇到过的编译器会产生一个错误,如果你这样做
#define true false
#defining
某些关键字可能会因为其他原因在编译时产生错误。 但是其中很多只会导致非常奇怪的程序行为。