简体   繁体   中英

C++: Creating a function object with mem_fn and bind1st

Disclaimer : This description contains a lot of Qt specific functionality. This is not necessary to answer the question, I'm just including it to explain the background.

I need to do some heavy computations in my QT application. In order to do this, I would like to use QtConcurrent::run(myFunction) This is Qt's version of async and creates a future, which at some point will contain the result of myFunction .

The problem is that the function is both a member function and takes complex parameters.

I know that you can pass both a function and a pointer to QtConcurrent::run. The function will then be invoked on the pointer. You can even provide a list of parameters. But it seems like this list only accepts parameters such as int , double or QString .

Actual Question:

I would like to convert this line of code:

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

into

myFunction()

That means I need to

  1. bind the pointer to the function
  2. bind the arguments to the function

This is my code so far:

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

Unfortunately this doesn't work. There are 18 compiler errors, here is the pastebin: http://pastebin.com/2rBQgFNL

It would be great, if you could explain how to do this properly. Not necessary for an answer, but even better, would be code for QtConcurrent::run.

Simply use a lambda expression.

auto myFunction = [&] { return model->nextStep(simulatedResult->last().molecules, dt); }

You could also use std::bind (see @JonathanWakely 's answer), but lamda expressions are imho more universal and powerful.

Also, keep in mind that reading and writing to the same memory from multiple threads will result in a data race (don't pass pointers/references to mutable data to the QT threads unless synchronization is used).

You're trying to mix the C++98 bind1st with the C++11 mem_fn , which isn't possible.

bind1st requires an adaptable binary function which means one that defines certain typedefs, and one that takes exactly two arguments. You can't use it with something that requires more than two and keep binding one argument at a time.

In C++11 it is possible to wrap function objects without those typedefs, thanks to decltype and other new features, so "adaptable binary function" is a useless concept now, and bind1st is useless and deprecated.

The solution is simply to use C++11 features instead of bind1st , eg std::bind or a lambda expression.

auto myFunction = std::bind( &ConcreteModel::nextStep, model, simulatedResult->last().molecules, dt);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM