Getting the address of the built-in function of the name of a friend

Consider the following code:

#include <iostream>

struct foo {
    friend void bar(foo) {}

    void foobar() {
        std::cout << &bar << '\n'; // error
    }
};

int main() {
    bar(foo{}); // ok, visible through ADL
    foo{}.foobar();
}

gcc gives me this error:

main.cpp: In member function 'void foo::foobar()':
main.cpp:7:23: error: 'bar' was not declared in this scope
         std::cout << &bar << '\n'; // error
                       ^~~

This is because it baris a friend function defined in the class itself, which makes it invisible in the global namespace. The only way to access it is through ADL, but I have not found a way to use ADL to get the address bar.

So my question is: how can I get the address bar? Is there any other way than to determine baroutside foo?

+6
source share
3 answers

You can declare a friend function in the encompassing area of ​​the namespace in another translation unit:

In foo.hpp:

#include <iostream>
struct foo;
void (*get_bar_address())(foo);
struct foo {
  friend void bar(foo) {}

  void foobar() {
      std::cout << get_bar_address() << '\n'; // no error
  } 
};

In foo.cpp

#include "foo.hpp"
void bar(foo);
void (*get_bar_address())(foo){
   return bar;
}
+2
source

, , . , , ++ 11 14

7.3.1.2

3 , , . , . (3.4.1) (3.4.3) , ( , ). , , , (3.4.2). , , , , , - .

, . , . , , .


, , bar, lambdas, ​​.

void foo::foobar() {
    using fntype = void(*)(foo);
    std::cout << (fntype)[](foo f){ bar(f); } << '\n'; // error
}

, , , . () -, .

+1

- ? , /, .

#include <iostream>

// forward declare foo so you can forward declare bar :)
struct foo;

// forward declare bar so an address is available on the line that references it.
void bar(foo);

struct foo 
{
    friend void bar(foo)
    {
       std::cout << "bar called" << std::endl;
    }

    void foobar() 
    {
        std::cout << "address of bar " << &bar << '\n'; // error
    }
};

int main() 
{
    bar(foo{}); // ok, visible through ADL
    foo{}.foobar();
}

LOL , :

$ ./test.exe
bar called
address of bar 1

although address 1 is suspicious. :) but hey he compiled and did something. maybe you can take it further, or someone can explain why this compiled / worked in the first place.

0
source

All Articles