ADL 是调用朋友内联函数的唯一方法吗?
Is ADL the only way to call a friend inline function?
让我们在 S
的声明中将 f
定义为 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
怎么办?
名称 f
在 friend declaration, even it becomes the member of the namespace which contains S
, but it's not visible for name lookup, unless it's redeclared at namespace scope. If not, it could be found only by ADL 中声明。
Names introduced by friend declarations within a non-local class X
become members of the innermost enclosing namespace of X
, but they do not become visible to ordinary name lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.
Is it true, then, that such an inline friend function can only be called with argument-dependant lookup?
是的。如 [namespace.memdef]/3 中指定:
If a friend
declaration in a non-local class first declares a class,
function, class template or function template. the friend is a member
of the innermost enclosing namespace. The friend declaration does not
by itself make the name visible to unqualified lookup
([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]).
由于 f
的 only 声明是其内联定义,因此它对合格或不合格的查找不可见。然而,ADL 对此类友元函数有特殊规定,[basic.lookup.argdep]/4:
When considering an associated namespace, the lookup is the same as
the lookup performed when the associated namespace is used as a
qualifier ([namespace.qual]) except that:
- Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective
namespaces even if they are not visible during an ordinary lookup
([class.friend]).
至于你的奖励问题,lambda 应该可以做到:
auto exposed_g = [](S const& s){ g(s); };
它将 ADL 包装到它的主体中。尽管有关 return 类型推导的常见警告适用。这将是一个值(假设您没有 return void
)。
没有。你应该正确地声明函数。
struct S;
inline void f();
inline void g(S const&);
struct S
{
friend void f() {}
friend void g(S const&) {}
} const s;
int main()
{
f(); // Ok
// S::f(); // error: 'f' is not a member of 'S'
g(s);
// S::g(s); // error: 'g' is not a member of 'S'
}
让我们在 S
的声明中将 f
定义为 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
怎么办?
名称 f
在 friend declaration, even it becomes the member of the namespace which contains S
, but it's not visible for name lookup, unless it's redeclared at namespace scope. If not, it could be found only by ADL 中声明。
Names introduced by friend declarations within a non-local class
X
become members of the innermost enclosing namespace ofX
, but they do not become visible to ordinary name lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.
Is it true, then, that such an inline friend function can only be called with argument-dependant lookup?
是的。如 [namespace.memdef]/3 中指定:
If a
friend
declaration in a non-local class first declares a class, function, class template or function template. the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]).
由于 f
的 only 声明是其内联定义,因此它对合格或不合格的查找不可见。然而,ADL 对此类友元函数有特殊规定,[basic.lookup.argdep]/4:
When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier ([namespace.qual]) except that:
- Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup ([class.friend]).
至于你的奖励问题,lambda 应该可以做到:
auto exposed_g = [](S const& s){ g(s); };
它将 ADL 包装到它的主体中。尽管有关 return 类型推导的常见警告适用。这将是一个值(假设您没有 return void
)。
没有。你应该正确地声明函数。
struct S;
inline void f();
inline void g(S const&);
struct S
{
friend void f() {}
friend void g(S const&) {}
} const s;
int main()
{
f(); // Ok
// S::f(); // error: 'f' is not a member of 'S'
g(s);
// S::g(s); // error: 'g' is not a member of 'S'
}