Функция Boost bind и boost, сохраняющая функции с аргументами в векторе и затем выполняющая их

Извините за плохо сформулированный заголовок.

Я просматривал документацию, но не нашел ничего, что могло бы решить эту проблему.

В основном я хочу сохранить несколько function1<void, void*> с предоставленными аргументами в векторе, а затем выполнить их на более позднем этапе.

Вот чего я хочу добиться:

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();
}

Теперь, выполняя task(), он хочет, чтобы я передал аргумент, но я передал его в AddSomeTasks? Почему это не используется? Или я неправильно понял использование boost::bind?

Спасибо


person KaiserJohaan    schedule 07.09.2012    source источник


Ответы (2)


ваш тип Task хочет аргумент, он должен был быть boost::function0<void>. Когда вы привязываете аргумент, возвращаемый (привязанный) вызываемый объект имеет арность 0, а не 1.

Кроме того, чтобы связать аргумент, вы указываете его для вызова boost::bind, _1 и т. д. предназначены для аргументов, которые оставлены несвязанными, а не то, что вам здесь нужно.

Что-то вроде (не проверено):

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();
}
person artm    schedule 07.09.2012
comment
Да, это именно то, что я хотел! Еще один момент: что если SomeTask будет функцией-членом, как тогда будет выглядеть синтаксис? - person KaiserJohaan; 08.09.2012
comment
если это функция-член, вы должны сначала связать объект: boost::bind(&Class::SomeTask, &object, (void*)&MyArg) (при условии, что object имеет тип Class) - person artm; 08.09.2012

Это зависит от того, когда вы хотите передать аргумент. Вызов push_back смешивает два разных понятия. Из сообщения неясно, хотите ли вы передать MyArgs во время вызова bind, и в этом случае вы получите объект функции, который не принимает аргументов и возвращает void, если вы хотите передать MyArgs во время выполнения задание. Для первого, как сказал @ForEveR, правильный вызов

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

и вам нужно изменить свой typedef для Task, чтобы он не принимал аргументов. Если вы хотите передать аргумент в точке вызова объекта task, то вызов push_back будет выглядеть так:

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

Это создаст объект функции с оператором вызова функции, который принимает один аргумент и возвращает void. Затем вы измените вызов на task() в ExecuteTask, чтобы передать любой аргумент, который у вас есть.

person Pete Becker    schedule 07.09.2012
comment
Я хочу передать MyArgs при вызове bind, я ошибся с синтаксисом _1 - person KaiserJohaan; 08.09.2012
comment
@KaiserJohaan - их легко запутать. - person Pete Becker; 08.09.2012
comment
когда я пытаюсь выполнить ExecuteTask(), а затем запустить task(), он по-прежнему запрашивает у меня аргумент для task(), хотя я хочу передать и сохранить его в AddSomeTasks(). Как бы я обойти это? - person KaiserJohaan; 08.09.2012
comment
Вы должны изменить свой typedef для Task, чтобы его operator() не принимал аргументов. typedef std::function<void(void)> Task; сделал бы это. Не знаю про Boost. - person Pete Becker; 08.09.2012