Search code examples
c++c++11qtconcurrentstdbind

std::bind, this and QtConcurrent


Im trying to use std::bind to bind this to method that is used in QtConcurrent::blockingMapped

Header:

class TuringMachine
{
private:
    TRTable table;
    std::set<ConfigNode*> currentConfigs;

    //function object
    std::function<std::set<ConfigNode*>( const TuringMachine*, ConfigNode*)> step_f;
    //method it will hold
    std::set<ConfigNode *> step(TuringMachine* this_m ,ConfigNode *parent);

    std::set<ConfigNode*>& makeStep();

}

Source:

    TuringMachine::TuringMachine(/**/)  
{

    step_f = std::bind(&TuringMachine::step, this, std::placeholders::_1);
}

std::set<ConfigNode*> &TuringMachine::makeStep(){

    auto configSet = QtConcurrent::blockingMapped<QLinkedList<std::set<ConfigNode*>>>(currentConfigs, step_f);//concurrent execution!

   /**/ 
   return currentConfigs;
}
std::set<ConfigNode*> TuringMachine::step(TuringMachine *this_m, ConfigNode * parent){     //the actual step
  /**/
}

So what Im doing here is running step conncurrently with blockingMapped on each ConfigNode in currentConfigs. Im using std::bind to bind this to step so it only requires one argument, as in the documentation of blockingMapped.

Im getting

error: no match for call to '(std::_Bind<std::_Mem_fn<std::set<ConfigNode*> (TuringMachine::*)(TuringMachine*, ConfigNode*)>(TuringMachine*, std::_Placeholder<1>)>) (const TuringMachine*, ConfigNode*)'
.../Qt/474/gcc/include/QtCore/qtconcurrentmapkernel.h:121: error: no match for call to '(std::function<std::set<ConfigNode*>(const TuringMachine*, ConfigNode*)>) (ConfigNode* const&)'
.../Qt/474/gcc/include/QtCore/qtconcurrentmapkernel.h:136: error: no match for call to '(std::function<std::set<ConfigNode*>(const TuringMachine*, ConfigNode*)>) (ConfigNode* const&)'

And note: 2 arguments expected, 1 provided

Where did I go wrong?

EDIT

Corrected, working version (for future "reference"):

Header:

    //function object
    std::function<std::set<ConfigNode*>( ConfigNode*)> step_f;
    //method it will hold
    std::set<ConfigNode *> step(ConfigNode *parent);

Source:

    TuringMachine::TuringMachine(/**/)  
{
    step_f = std::bind(&TuringMachine::step, this, std::placeholders::_1);
}

Solution

  • If you want to bind a member function, you would have to pass a this pointer, which in your case would mean that you would have to pass 2 this-pointers:

    Normal call to member function:

    struct bar {
      int a;
      void foo() {
        std::cout << a << std::endl;
      }
    
      void call_yourself() {
         auto f = std::bind(&bar::foo, this);
         f();
      }
    };
    

    Your case:

        step_f = std::bind(&TuringMachine::step, this, this,std::placeholders::_1);
    

    Without understanding your code, I would probably redesing your code such that you can avoid the double this pointer.