§3.4.1/3 有以下示例:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);
}
};
}
编译时不会出现错误(请参阅 live example ),因为编译器看不到友元声明 N::A::f(A&)
在名称 f
的普通查找中在声明中int i = f(a);
根据 §7.3.1.2/3,这是正确的。
§7.3.1.2/3(重点是我的):
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship).
现在,如果我们包含声明
struct A;
void f(A&);
在上面的代码片段 namespace N
中,之前struct A
,代码将正确地发出错误(参见 live example ),就像现在的函数 ::f(A&)
一样。通过普通查找名称 f
即可找到在表达式 int i = f(a);
中这符合 §7.3.1.2/3。
但是,如果我们包含声明
void f(A&);
在 namespace N
,在struct A
之后,令人惊讶的是,代码没有发出任何错误,请参阅 live example .
最佳答案
不,clang 正在做正确的事情。这不是一个错误。
您误读了本规范摘录的上下文。本段唯一要传达的内容涉及友元函数声明及其目标函数如何相互关联。 它与调用特定函数的通常规则没有任何关系,并且在这方面没有任何改变。
因此,编译不会失败,因为函数 f()
的原型(prototype)在您尝试使用它时尚未声明(而是找到具有相同名称的 typedef)。
如果您更改代码以在类外部实现 A::g()
成员,您会注意到当 f()
原型(prototype)出现时编译失败在实现之前,当原型(prototype)出现在它之后时成功——这正是您在缺少友元声明时所期望发生的情况。
关于c++ - 好友声明 : Is this a bug in clang?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25672745/