C++: создание объекта функции с помощью mem_fn и bind1st
Отказ от ответственности: Это описание содержит много специфических функций Qt. Это не обязательно, чтобы ответить на вопрос, я просто включаю его, чтобы объяснить фон.
Мне нужно сделать несколько тяжелых вычислений в моем приложении QT. Для этого я бы хотел использовать QtConcurrent::run(myFunction)
Это версия асинхронного Qt и создает будущее, которое в какой-то момент будет содержать результат myFunction
,
Проблема в том, что функция является одновременно функцией-членом и принимает сложные параметры.
Я знаю, что вы можете передать как функцию, так и указатель на QtConcurrent::run. Функция будет вызываться по указателю. Вы даже можете предоставить список параметров. Но кажется, что этот список принимает только такие параметры, как int
, double
или же QString
,
Актуальный вопрос:
Я хотел бы преобразовать эту строку кода:
model->nextStep(simulatedResult->last().molecules, dt)
в
myFunction()
Это означает, что мне нужно
- привязать указатель к функции
- привязать аргументы к функции
Это мой код до сих пор:
auto memfun=std::mem_fn(&ConcreteModel::nextStep);
auto memfun_bound_to_model=std::bind1st(memfun,model);
auto memfun_bound_result=std::bind1st(memfun_bound_to_model,simulatedResult->last().molecules);
auto memfun_bound_dt=std::bind1st(memfun_bound_result,dt);
К сожалению, это не работает. Есть 18 ошибок компилятора, вот pastebin: http://pastebin.com/2rBQgFNL
Было бы здорово, если бы вы могли объяснить, как это сделать правильно. Не обязательно для ответа, но даже лучше, будет код для QtConcurrent::run.
2 ответа
Просто используйте лямбда-выражение.
auto myFunction = [&] { return model->nextStep(simulatedResult->last().molecules, dt); }
Вы также можете использовать std::bind
(см. ответ @JonathanWakely), но выражения lamda являются более универсальными и мощными.
Также имейте в виду, что чтение и запись в одну и ту же память из нескольких потоков приведет к гонке данных (не передавайте указатели / ссылки на изменяемые данные в потоки QT, если не используется синхронизация).
Вы пытаетесь смешать C++98 bind1st
с C++11 mem_fn
, что невозможно.
bind1st
требует адаптируемой двоичной функции, которая означает функцию, которая определяет определенные определения типов, и функцию, которая принимает ровно два аргумента. Вы не можете использовать это с чем-то, что требует больше двух и продолжать связывать один аргумент за раз.
В C++11 можно обернуть функциональные объекты без этих typedefs, благодаря decltype
и другие новые функции, так что "адаптируемая двоичная функция" теперь бесполезна, и bind1st
бесполезен и не рекомендуется.
Решение состоит в том, чтобы просто использовать функции C++11 вместо bind1st
например, std::bind
или лямбда-выражение.
auto myFunction = std::bind( &ConcreteModel::nextStep, model, simulatedResult->last().molecules, dt);