我期望以下程序在GCC或Clang中会发出诊断信息:
#undef protected
#undef private
由于[macro.names] / 2:
翻译单元不得定义或取消定义与关键字、表3中列出的标识符或7.6中描述的属性令牌在词汇上完全相同的名称。
“protected”和“private”都列在表3中。通过对N3337进行“无需诊断”的快速查找,未发现任何内容。因此,编译器在这种情况下是否需要报错?
我期望以下程序在GCC或Clang中会发出诊断信息:
#undef protected
#undef private
[macro.names]是[reserved.names]的一部分,其中规定:“如果程序在保留上下文中声明或定义名称,除非显式允许,否则其行为是未定义的。”因此它的行为是未定义的。
实际上,大多数编译器不会抱怨有两个原因:第一个是因为预处理通常在编译器评估符号是否为关键字之前进行;这是翻译的早期阶段。而且因为只有在你实际使用标准库时,这样的声明才是非法的(尽管其他库,如Posix或Windows,可能并且可能实施类似的规则)。
编辑:
仅作一般性评论:虽然标准中没有全局说明,但是存在一个一般的基本原则,即违反库约束是未定义的行为;意图是编译器不需要了解库,并且实现可以像#include "MyHeader.hpp"
一样精确地对待#include <vector>
(除了它可能寻找文件的位置)。原始帖子中引用的限制是针对使用库的程序的约束,并且仅适用于这些程序。类似于:
#define while if
int
main( int argc, char** argv )
{
int retval = 0;
while ( argc > 0 ) {
++ retval;
-- argc;
}
return retval;
}
这是一个完全合法的 C++(和 C)程序,保证返回 1。(当然,我不建议这样做。)
是的,但实际上大多数人并没有。Clang 最近才得到一个警告。
#undef private
可能不会产生预期的效果。这不是这种情况吗? - The Paramagnetic Croissant#define private public
是违反一个定义规则的好方法。) - James Kanze