TrevorPeyton
TrevorPeyton

Reputation: 669

C++ Store Function without Argument

Say that you define a callback function as such:

typedef std::function<void(float)> Callback;

And you have a function as such:

void ImAFunction(float a)
{
    //Do something with a
}

Is there a way to be able to store a function without an argument then pass one to it at a later time?

Such as this:

//Define the Callback storage
Callback storage;

storage = std::bind(ImAFunction, this);

//Do some things

storage(5);

This wont work which I explain with some of my real code below.

I can get close to what I wan't if I bind the value in with the std::bind function. Such as:

//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed

This works but when I go to pass a value through the function the outcome is whatever I set it to before:

storage(100); //Output is still 5

I am basing the fact that I think this is possible on this article.

http://www.cprogramming.com/tutorial/function-pointers.html

It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.

The error produced above comes from this code:

struct BindInfo {
    Callback keyCallback;
    int bindType;
    bool isDown;
    bool held;
    std::string name;
};

template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
    BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };

    inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};

The error is:

No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'

Is this possible? Thanks in advance.

Upvotes: 1

Views: 1352

Answers (2)

Kyle W
Kyle W

Reputation: 64

It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:

void (*IAmAFunctionPointer)(float) = &IAmAFunction;

The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:

float a = 5;
IAmAFunctionPointer(a);

You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).

    void DoStuffThenCallback(float a, void (*callback)(float))
    {
     //DoStuff
     callback(a);
    }

further reading: http://www.cprogramming.com/tutorial/function-pointers.html

Upvotes: 0

Mike Seymour
Mike Seymour

Reputation: 254471

You can include a placeholder for an unbound argument:

std::bind(&Main::ImAFunction, this, std::placeholders::_1);

If you find that a bit of a mouthful, a lambda might be more readable:

[this](float a){ImAFunction(a);}

Upvotes: 2

Related Questions