让我们在f
的声明中将S
定义为S
的朋友函数:
struct S
{
friend void f() {}
};
我找不到呼叫f
的方法。
是真的,这样的内联好友函数只能用argument-dependant lookup调用吗?
struct S
{
friend void f() {}
friend void g(S const&) {}
} const s;
int main()
{
// f(); // error: 'f' was not declared in this scope
// S::f(); // error: 'f' is not a member of 'S'
g(s);
// S::g(s); // error: 'g' is not a member of 'S'
}
奖金:如果我想获得一个函数指针/ std::function
/ lambda到g
,该怎么办?
答案 0 :(得分:10)
那么,这样的内联好友函数只能通过依赖于参数的查找来调用吗?
是的。根据{{3}}中的规定:
如果非本地类中的
friend
声明首先声明了一个类, 函数,类模板或函数模板。朋友是会员 最内层的封闭命名空间。朋友声明不 本身使名称可见以进行不合格的查找 ([basic.lookup.qual)]或合格的查找([basic.lookup.qual])。
由于f
的 only 声明是其内联定义,因此对于合格或不合格的查找而言,它均不可见。但是,ADL对此类朋友功能有特殊规定,[namespace.memdef]/3:
在考虑关联的名称空间时,查找与 当关联的名称空间用作 限定符([namespace.qual]),除了:
- 在关联类中声明的任何命名空间范围的好友函数或好友函数模板在它们各自的内部可见 命名空间,即使它们在普通查找中不可见 ([class.friend])。
关于您的奖金问题,lambda应该这样做:
auto exposed_g = [](S const& s){ g(s); };
它将ADL包装到其主体中。尽管适用有关归还类型扣除的常见警告。这将是一个值(假设您不返回void
)。
答案 1 :(得分:8)
名称f
是在friend declaration中声明的,即使它成为包含S
的{{3}}的成员,但对于名称查找来说它是不可见的,除非它是在名称空间范围内重新声明。如果没有,则只能由namespace找到。
由非本地类
X
中的朋友声明引入的名称成为X
最内层封闭名称空间的成员,但除非普通名称查找(无论是合格还是合格),否则它们不会变为可见在类定义之前或之后,在名称空间范围内提供了一个匹配的声明。可以通过同时考虑名称空间和类的ADL找到该名称。
答案 2 :(得分:2)