我有以下代码:
struct M {
friend void f() {}
M() {
f(); // error: 'f' was not declared in this scope
}
};
int main() {
M m;
}实例化
g++4.8和clang3.4都无法编译它,因为f在M中是不可见的,或者他们这么说。
但是,标准给出了一个类似代码的示例
class M {
friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};并说
类中定义的
friend函数位于定义类的(词法)范围内。
(ISO/IEC 14882:2011 11.3之友class.friend p6,p7)
由此,我无法理解编译器如何找不到在使用它的同一个类中定义的f。
这两个编译器不太可能有相同的bug。
我错过了什么?
发布于 2014-05-08 12:01:41
friend声明指出,在周围的名称空间中名为f的函数是类的朋友;但是它没有将名称f引入名称空间。在命名空间中声明之前,它是不可用的(依赖于参数的查找除外)。
相关规则是C++11 7.3.1.2/3:
如果非本地类中的
friend声明首先声明一个类或函数,则朋友类或函数是最内部的封闭命名空间的成员。朋友的名字不通过非限定查找或限定查找找到,直到在该命名空间范围中提供匹配声明为止。
发布于 2014-05-08 11:59:19
这是来自C++标准的引用
在类中定义的朋友函数位于定义它的类的(词法)范围内。
表示以下内容:
9.在授予友谊的类中定义的朋友函数(11.3)的定义中使用的名称查找应按照成员函数定义中所描述的查找方式进行。
也就是说,从类范围开始搜索函数中使用的任何名称。
但是,函数本身在名称空间中是不可见的,除非它在类之外声明。
因此,在您的例子中,在类定义之前声明函数就足够了。
void f() {}
struct M {
friend void f();
M() {
f();
}
};
int main() {
M m;
}或
void f();
struct M {
friend void f() {}
M() {
f();
}
};
int main() {
M m;
}发布于 2014-05-08 12:01:59
关键问题是在什么情况下编译器能够/允许找到函数声明。对于一般的friend函数,您必须在类之外声明它,以便编译器能够找到它。
但是,有一个非常有用的例外:如果friend函数有一个类类型的参数,那么它能够找到函数,而不需要参数依赖的名称查找带来的额外声明。
这种情况实际上非常重要,因为通常您希望friend函数访问类类型的对象。
请考虑以下示例:
#include <iostream>
struct M
{
friend void printI(int a) {
std::cout << a;
}
friend void print(const M& m) { // friend takes object of class type!
std::cout << "M";
}
void foo() {
printI(2); // ERROR - requires declaration!
print(*this); // OK!
}
};
int main()
{
M m;
m.foo();
printI(2); // ERROR - requires declaration!
print(m); // OK
}https://stackoverflow.com/questions/23540764
复制相似问题