creativeflow
creativeflow

Reputation: 178

C++ Callback function, calling member variable inside static function

I've recently decided to start working with callback functions to make my life a bit easier. However, I'm having a bit of an issue:

#include <iostream>
#include <functional>
#include <memory>

class setCallback
{
public:
        setCallback() {}
        setCallback(std::function<int()> func) : callback(func) { }

        int call() { return callback(); }
private:
        std::function<int()> callback;
};

class callThis
{
public:
        callThis() : number(10) {}

        static int another()
        {
                return number;
        }
        int number;
};

int main(int argc, char** argv[])
{
        std::shared_ptr<setCallback> caller;
        std::shared_ptr<callThis> funcholder;

        funcholder.reset(new callThis);
        caller.reset(new setCallback(funcholder->another));

        std::cout << caller->call() << "\n";

        std::cin.get();
}

As you can see from the code, I pull in the function from "callthis" into "setCallBack". This allows me to keep the function for later use, if needed. This works perfectly, however, if I attempt to load in a member variable from "callthis" into the static function, it obviously would not work (using a value does).

Is there a way around this? I would like to access the variable found within the class using the static function; optionally avoid using static functions when passing into the callback (but I assume this isn't possible due to the way callbacks work).

I've heard about wrapper classes but I'm not entirely sure how I would go about implementing it. Some insight would be appreciated.

Thanks a lot.

Edit:

Solved calling variables with callback functions, by B Sahu

Solved calling functions using callbacks without making the function being called static and keeping things reasonably uncoupled

I researched how to call non-static functions using C++11; I thought it might be useful if anyone ends up having the same issues I do. This works on the same principles as R Sahu proposed, however, using types and procedures found in it ends up being a bit cleaner. Using std::bind(class::func, object) you can effectively gain the same results.

int main(int argc, char** argv)
{
    std::function<void(void)> somefunc;

    Functionholder func;

    somefunc = std::bind(&Functionholder::say, &func);
}

Credit for this goes to: This beautiful person

Which when used in a more complex example, having a class which holds the function to call, a caller class which will take the function and call it when required and a binder/state class (note, i'm using this for game UI), you can really get some reasonably neat and uncoupled code going:

#include <iostream>
#include <functional>

class Functionholder
{
public:
    void say() { std::cout << "hello!\n"; }
};

class CallbackHandler
{
public:
    CallbackHandler(){}
    CallbackHandler(std::function<void()> call) { callback = call; }

    void update() 
    { 
        //something happens to call this
        callback();
    }

    std::function<void()> callback;
};

class TheState
{
public:
    TheState()
    {
        hand = CallbackHandler(std::bind(&Functionholder::say, &func));
    }

    void update() { hand.update(); }

    Functionholder func;
    CallbackHandler hand;
};

int main(int argc, char** argv)
{
    TheState state;
    state.update();

    std::function<void(void)> somefunc;

    std::cin.get();
}

If you have any improvements let me know!

Upvotes: 0

Views: 4995

Answers (1)

R Sahu
R Sahu

Reputation: 206587

Provide the ability to call the callback functions with user specified data. Then, use the data in the callback function.

#include <iostream>
#include <functional>
#include <memory>

class setCallback
{
   public:
      setCallback() {}
      setCallback(std::function<int(void*)> func) : callback(func) { }

      int call(void* data) { return callback(data); }
   private:
      std::function<int(void*)> callback;
};

class callThis
{
   public:
      callThis() : number(10) {}

      static int another(void* data)
      {
         callThis* ptr = static_cast<callThis*>(data);
         return ptr->number;
      }
      int number;
};

// Fixed this line. You had
// int main(int argc, char** argv[])
int main(int argc, char** argv)
{
   std::shared_ptr<setCallback> caller;
   std::shared_ptr<callThis> funcholder;

   funcholder.reset(new callThis);
   caller.reset(new setCallback(callThis::another));

   std::cout << caller->call(funcholder.get()) << "\n";

   std::cin.get();
}

Upvotes: 1

Related Questions