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