Search code examples
c++callbackc++17pointer-to-member

Calling a callback passed from another class


I want to register a callback handler (method) of the one class (Y) in another (X). I can't use std::function because of possible heap allocation and I must have an access to members of a class that registers the handler. I also want to avoid static functions. I've came up with some workaournd but got stuck on calling the callback:

template<class T>
using clbkType = void(T::*)(void);

template<class T>
class X
{
public:

    void registerClbck(clbkType<T> clbk) {
        callback = clbk;
    }

    void call() {
        callback(); // ERROR C2064: term does not evaluate to a function taking 0 arguments.
        //(((X<T>*)this)->X<T>::callback)(); // same error

    }
private:
    clbkType<T> callback;
};

class Y
{
public:

    Y() {
        x.registerClbck(&Y::handler);
    }

    // just for a test: fire a callback in class X
    void fire() {
        x.call();
    }

    int getA() { return a; }
private:
    int a{ 0 };
    X<Y> x{};

    void handler() {
        a = 5;
    }
};

int main()
{
    Y y;
    y.fire();
    return y.getA();
}

link to code: https://godbolt.org/z/PhY41xsWE

PS. I'm not sure if this is a safe solution, so please put any comment on that.

Thanks!


Solution

  • The member function pointer needs a specific class object to invoke, so you need to do this:

    template<class T>
    class X
    {
    public:
        // ...
        void call(T& obj) {
          (obj.*callback)();
        }
        // ...
    };
    
    class Y
    {
    public:
        // just for a test: fire a callback in class X
        void fire() {
          x.call(*this);
        }
        // ...  
    };
    

    Demo.