Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 338
YSC Avatar asked Jul 12 '18 11:07

YSC


People also ask

Can a friend function be inline?

Inline friend definitionsFriend functions can be defined (given a function body) inside class declarations. These functions are inline functions.

Can we call friend function without object?

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.

How friend function is called?

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.

What is the difference between inline function and friend 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.


1 Answers

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

like image 76
StoryTeller - Unslander Monica Avatar answered Sep 24 '22 06:09

StoryTeller - Unslander Monica