Call a hidden friend function

145 Views Asked by At

Consider the following code:

struct A
{
    friend void foo(A& a) {}
};
struct B
{
    void foo()
    {
        A a;
        foo(a); // doesn't compile because "foo" friend function is hidden
    }
};

int main()
{
    A a;
    foo(a); // OK here
}

In function main, I can easily call friend function foo defined inside class A.

In function B::foo the same code doesn't compile because the friend function foo is hidden inside class B by its member function.

In there a way to call the original hidden function inside B, without renaming B::foo? I tried to use ::foo(a); or A::foo(a); but those don't compile neither.

2

There are 2 best solutions below

2
user12002570 On BEST ANSWER

In there a way to call the original hidden function inside B, without renaming B::foo?

Yes there is by adding the declaration void foo(A& a) inside the member function void B::foo()as shown below. This also meets your requirement that you don't want to rename B::foo.

Basically we're making use of forward declaration here.

struct A
{
    friend void foo(A& a) {}
};

struct B
{
    void foo()
    {
        A a;
        void foo(A&); //added this declaration
        foo(a); //compiles now
    }
};

Working demo

0
Serge Ballesta On

In fact, friend void foo(A& a) {}; does not declare a method of A, but says that the top level function foo is friend of A, meaning that ::foo can access any private member of A. Simply as it is only declared inside A namespace, it may be inlined by the compiler, and the symbol foo may not exist in the global namespace.

You just have to declare it in the global namespace before using it in B.

Then, inside B::foo, you can either qualify it with ::foo or use using to say that inside that bloc foo will be ::foo and not B::foo:

void foo(A&);
struct B
{
    void foo()
    {
        A a;
        ::foo(a); // compiles fine
    }
};

or

void foo(A&);
struct B
{
    void foo()
    {
        using ::foo;
        A a;
        foo(a); // compiles fine too...
    }
};