klefevre klefevre - 2 months ago 9
C++ Question

How passing arguments using std::mem_fun

I would know if there is a way to pass arguments using std::mem_fun ?
I want to precise that I can have as much arguments as possible and a lot of member functions.

The problem is that I'm on an old standard and I'm looking for a full stl way so boost isn't allowed as answer even if I know I could do it easily =/

Here is a little illustration of how I wanna use it :


#include <list>
#include <algorithm>

// Class declaration
//
struct Interface {
virtual void run() = 0;
virtual void do_something(int) = 0;
virtual void do_func(int, int) = 0;
};

struct A : public Interface {
void run() { cout << "Class A : run" << endl; }
void do_something(int foo) { cout << "Class A : " << foo << endl; }
void do_func(int foo, int bar) { cout << "Class A : " << foo << " " << bar << endl; }
};

struct B : public Interface {
void run() { cout << "Class B : run" << endl; }
void do_something(int foo) { cout << "Class B : " << foo << endl; }
void do_func(int foo, int bar) { cout << "Class B : " << foo << " " << bar << endl; }
};

// Main
//
int main() {
// Create A and B
A a;
B b;

// Insert it inside a list
std::list<Interface *> list;
list.push_back(&a);
list.push_back(&b);

// This works
std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::run));

// But how to give arguments for those member funcs ?
std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_something));
std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_func));
return 0;
}

Answer

Use std::bind via std::bind1st and std::bind2nd

std::for_each(list.begin(), list.end(),
              std::bind2nd(std::mem_fun(&Interface::do_something),1) // because 1st is this
             );

Unfortunately, the standard does not help for the two arguments version and you need to write your own:

struct MyFunctor
{
    void (Interface::*func)(int,int);
    int         a;
    int         b;

    MyFunctor(void (Interface::*f)(int,int), int a, int b): func(f), a(a), b(b) {}

    void operator()(Interface* i){ (i->*func)(a,b);}
};

std::for_each(list.begin(), list.end(),
              MyFunctor(&Interface::do_func, 1, 2)
             );
Comments