cppprogrammer
cppprogrammer

Reputation: 135

Converting pointer to member function to std::function

I have a slightly convoluted use case of passing a member function pointer to an outside function which is then called again by a member function (Don't ask!). I'm learning about std::function and std::mem_fn but I can't seem to be able to convert my old school function pointer

void (T::*func)(int) to a std::function<void (T::*)(int) func>

in the code below, I'd like to be able to pass a std::function to memFuncTaker in the call from anotherMember

#include "class2.hpp" 
#include <iostream> 

class outer{ 
public: 
  void aMember(int a){ 
    std::cout << a <<std::endl; 
  } 
  void anotherMember(double){ 
    memFuncTaker(this, &outer::aMember); 
  } 

}; 


template<class T> 
void memFuncTaker(T* obj , void (T::*func)(int) ){ 
  (obj->*func)(7); 
} 

Upvotes: 2

Views: 5529

Answers (1)

AnT stands with Russia
AnT stands with Russia

Reputation: 320381

When you bind std::function to a non-static member function pointer, it "reveals" the hidden this parameter, making it the first explicit parameter of the resultant functor. So in your case for outer::aMember you'd use std::function<void(outer *, int)> and end up with a two-parameter functor

#include <functional>
#include <iostream> 

template<class T> 
void memFuncTaker(T *obj , std::function<void(T *, int)> func){ 
  func(obj, 7);
} 

class outer{ 
public: 
  void aMember(int a){ 
    std::cout << a <<std::endl; 
  } 
  void anotherMember(double){ 
    memFuncTaker(this, std::function<void(outer *, int)>{&outer::aMember}); 
  } 
}; 

int main() {
  outer o;
  o.anotherMember(0);
}

http://coliru.stacked-crooked.com/a/5e9d2486c4c45138

Of course, if you prefer, you can bind the first argument of that functor (by using std::bind or lambda) and thus "hide" it again

#include <functional>
#include <iostream> 

using namespace std::placeholders;

void memFuncTaker(std::function<void(int)> func){ 
  func(7);
} 

class outer{ 
public: 
  void aMember(int a){ 
    std::cout << a <<std::endl; 
  } 
  void anotherMember(double){ 
    memFuncTaker(std::function<void(int)>(std::bind(&outer::aMember, this, _1))); 
  } 
}; 

int main() {
  outer o;
  o.anotherMember(0);
}

Note that in this version memFuncTaker no longer has to be a template (which happens to be one of the primary purposes of std::function - employ type erasure techniques to "de-templatize" the code).

Upvotes: 2

Related Questions