Is ADL the only way to call a friend inline function?

  • A+
Category:Languages

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?

 


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).

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: