C++: создание объекта функции с помощью mem_fn и bind1st

Отказ от ответственности: Это описание содержит много специфических функций Qt. Это не обязательно, чтобы ответить на вопрос, я просто включаю его, чтобы объяснить фон.

Мне нужно сделать несколько тяжелых вычислений в моем приложении QT. Для этого я бы хотел использовать QtConcurrent::run(myFunction) Это версия асинхронного Qt и создает будущее, которое в какой-то момент будет содержать результат myFunction,

Проблема в том, что функция является одновременно функцией-членом и принимает сложные параметры.

Я знаю, что вы можете передать как функцию, так и указатель на QtConcurrent::run. Функция будет вызываться по указателю. Вы даже можете предоставить список параметров. Но кажется, что этот список принимает только такие параметры, как int, double или же QString,

Актуальный вопрос:

Я хотел бы преобразовать эту строку кода:

model->nextStep(simulatedResult->last().molecules, dt)

в

myFunction()

Это означает, что мне нужно

  1. привязать указатель к функции
  2. привязать аргументы к функции

Это мой код до сих пор:

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);
Другие вопросы по тегам