ggininder
ggininder

Reputation: 161

What's the correct way to let the static member function call a non-static member std::function in c++?

I'm using an open62541 library who's functions are almost all static. I have to write some callback functions in the open62541's functions, the callback functions are binding to some non-static function.

so the problem is how do I make the:

static function of class A call a std::function, which is bind to non-static function of class B ?

to make the question simpler I make the example:

#include <iostream>
#include <functional>
using namespace std;

    namespace C {
    std::function<void(void)>C_foo;
    }
    class B
    {
    public:
        B()
        {
            C::C_foo=std::bind(&B::middleMan,this);
        }
        std::function<void(void)>B_foo;
        void middleMan()
        {
            B_foo();
        }
        static void talkTheJoke()
        {
            C::C_foo();
        }
        
    };
    class A
    {
    public:
        void Knock_knock()
        {
            std::cout<<"who's there?"<<std::endl;
        }
    };
    int main()
    {
        A m_A;
        B m_B;
        // response "who's there?"
        m_A.Knock_knock();

        m_B.B_foo=std::bind(&A::Knock_knock,m_A);
        
        //response "who's there?" again "
        B::talkTheJoke();
        
        return 0;
    }

There are class A and their non-static member function A:: Knock_knock(), I want class B's static member function can callback and also acts the same as A:: Knock_knock().

I put a B_foo there as a callback function which would bind the A:: Knock_knock(). Since the B::talkTheJoke() is static and B_foo is not, it seems that B::talkTheJoke() cannot call the B_foo.

So I put a namespace C as a middle man, the std:: function in C can be called by static function B::talkTheJoke(), it can also be bind to non-static std:: function B:: middleMan() which can call the B_foo.

The story would look like:

B::talkTheJoke() ----> m_B.B_foo --(std::bind)--> m_A.Knock_knock() ( X , not works )

B::talkTheJoke() ----> C::C_foo() --(std::bind)--> m_B.middleman() ----> m_B.B_foo --(std::bind)--> m_A.Knock_knock() ( O ,works )

However, this solution is really ugly,

what's the correct way to do so?

Upvotes: 0

Views: 278

Answers (1)

Allen Zhu
Allen Zhu

Reputation: 870

#include <iostream>
using namespace std;

class A
{
public:
    void Knock_knock() {
        std::cout<<"who's there?"<<std::endl;
    }
};

class B
{
public:
    static void setA( A *a ) {
        m_A = a;
    }

    static void talkTheJoke() {
        if ( m_A != nullptr )
            m_A->Knock_knock();
    }

private:
    static A *m_A;
};

A* B::m_A = nullptr;

int main()
{
    A m_A;
    m_A.Knock_knock();

    B::setA( &m_A );
    B::talkTheJoke();
    return 0;
}

Upvotes: 1

Related Questions