我正在尝试确定是否针对 Clang、GCC 或两者提交错误报告(我已经针对 Clang 主干和 GCC 4.7.2 进行了测试:如果有人可以针对 GCC 主干验证这一点会有所帮助):
基本上,以下代码三行文件-fsyntax-only
在默认和 C++11 模式下可以正常编译:
class A {
friend void f();
};
请注意,没有事先声明f()
,但这显然是可以的。
但是,Clang(但不是 GCC)拒绝以下内容:
class A {
friend void ::f();
};
Clang 的错误是“在指定范围内没有找到类型为 'void ()' 的名为 'f' 的函数”,但我在标准中找不到任何理由来区别对待这种情况,所以我认为这是一个错误;不过我可能是错的(但是,我正在阅读 N3242,AFAIK 是 C++11 之前的最后一个公开草案)。
然而,下一个示例被 GCC 而不是 Clang 拒绝:
void f() { }
void g()
{
class A {
friend void ::f();
};
}
来自 GCC 的错误是“本地类中没有事先声明的朋友声明 'void f()'”,这似乎没有意义,因为void ::f()
应该引用f()
已声明的全局命名空间中的 。(不要介意friend
- 从本地类中调用全局函数是荒谬的,它似乎并不违法......)
最后,最后一个示例被 Clang 和 GCC 拒绝:
void g()
{
class A {
friend void ::f();
};
}
错误分别是“在本地类中没有事先声明的朋友声明'void f()'”和“在指定范围内找不到名为'f'且类型为'void ()'的函数”。现在,从 11.4p11 开始,似乎有一些理由拒绝本地类中先前未声明的函数的朋友声明,但该段实际上是:
如果友元声明出现在本地类 (9.8)中并且指定的名称是非限定名称,则在不考虑最内层非类范围之外的范围的情况下查找先前的声明。对于友元函数声明,如果没有事先声明,则程序是非良构...
该声明的非法性显然是基于本段中的第二句话,但我不清楚该句子是否也应适用于限定名称的情况,正如在本案中使用的那样。(可以说,无论是否使用“非限定名称”,整个段落都可能适用于“本地类”情况,并且“并且指定的名称是非限定名称”子句仅适用于所描述的查找在第一句话中,但这似乎有点牵强……我认为这是一种可能性的唯一原因是因为两个编译器都拒绝它。)
无论如何,据我所知,所有这四个案例(无论它们是否合理)都应该是合法的;即使不是,在第二种和第三种情况下,Clang 和 GCC 中至少有一个是错误的。谁能在我的逻辑中找到错误?
第三种和第四种情况无疑是荒谬的。但我可以看到第二种情况破坏了某人的有效和有用的代码,所以我有点惊讶它从未被抓住,如果它确实是一个错误。