KaiserJohaan
KaiserJohaan

Reputation: 9240

Boost bind and boost function, storing functions with arguments in a vector and then executing them

Sorry for the badly-worded title.

I've been looking through the documentation, but I cannot find anything that might solve this problem I have.

Basically I want to store several function1<void, void*> , with arguments provided, in a vector, and then execute them at a later stage.

This is what I want to accomplish:

typedef boost::function1<void, void*> Task;

Vector<Task> mScheduledTasks;
int MyArg = 5;

void SomeTask(void* arg)
{
    // ....
}

void AddSomeTasks()
{
    // nevermind that MyArg is globally accessible
    for (int i = 0; i<5; i++)
        mScheduledTasks.push_back(boost::bind(&SomeTask, _1), (void*)&MyArg);
}

void ExecuteTask()
{
    Task task = mScheduledTasks.front();
    task();
}

Now executing task() it wants me to pass an argument, but I passed it in AddSomeTasks? Why is it not using that? Or I have missunderstod the usage of boost::bind?

Thanks

Upvotes: 4

Views: 3822

Answers (2)

Pete Becker
Pete Becker

Reputation: 76305

It depends on when you want to pass the argument. The push_back call mixes two different notions. It's not clear from the message whether you want to pass MyArgs at the time you call bind, in which case you'll get back a function object that takes no arguments and returns void, of if you want to pass MyArgs at the time you execute the task. For the former, as @ForEveR said, the correct call is

mScheduledTasks.push_back(boost::bind(&SomeTask, (void*)&MyArg));

and you need to change your typedef for Task so that it takes no arguments. If you want to pass the argument at the point of the call to the task object, then the push_back call would look like this:

mScheduledTasks.push_back(boost::bind(&SomeTask, _1));

That will create a function object with a function call operator that takes one argument and returns void. Then you'd change the call to task() in ExecuteTask to pass whatever argument you have.

Upvotes: 3

artm
artm

Reputation: 3678

your Task type wants an argument, it should have been boost::function0<void>. When you bind an argument, the returned (bound) callable object is of arity 0, not 1.

Also, to bind an argument you supply it to the call to boost::bind, the _1 etc are for arguments that are left unbound, not what you want here.

Something like (untested):

typedef boost::function0<void> Task;

Vector<Task> mScheduledTasks;
int MyArg = 5;

void SomeTask(void* arg)
{
    // ....
}

void AddSomeTasks()
{
    // nevermind that MyArg is globally accessible
    for (int i = 0; i<5; i++)
        mScheduledTasks.push_back(boost::bind(&SomeTask, (void*)&MyArg));
}

void ExecuteTask()
{
    Task task = mScheduledTasks.front();
    task();
}

Upvotes: 4

Related Questions