Let us define f
, as a friend function of S
, inside the declaration of S
:
struct S { friend void f() {} };
I cannot find a way to call f
.
Is it true, then, that such an inline friend function can only be called with 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' }
Bonus: what if I want to get a function-pointer/std::function
/lambda to g
?
Inline friend definitionsFriend functions can be defined (given a function body) inside class declarations. These functions are inline functions.
A friend function can be declared in the private or public section of the class. It can be called like a normal function without using the object.
A friend function can be declared in the private or public part of a class without changing its meaning. Friend functions are not called using objects of the class because they are not within the class's scope. Without the help of any object, the friend function can be invoked like a normal member function.
There's no difference. Both friend and inline are independent declaration specifiers, which can be specified in any order. There's not much point in declaring the function inline in a friend declaration though. More generally, there's no point in specifying inline in any non-defining function declaration.
Is it true, then, that such an inline friend function can only be called with argument-dependant lookup?
Yes. As specified in [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]).
Since the only declaration of f
is its inline definition, it's not made visible to qualified or unqualified lookup. ADL however, has a special provision for such friend functions, [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]).
As for your bonus question, a lambda should do it:
auto exposed_g = [](S const& s){ g(s); };
It wraps the ADL into its body. Though the usual caveats about return type deduction apply. It will be a value (assuming you don't return void
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With