Как передать аргументы используя std :: mem_fun - PullRequest
5 голосов
/ 15 марта 2012

Я бы знал, если есть способ передать аргументы, используя std :: mem_fun?Я хочу уточнить, что у меня может быть как можно больше аргументов и много функций-членов.
Проблема в том, что я нахожусь на старом стандарте и ищу полный путь STL, поэтому повышение не разрешенов качестве ответа, даже если я знаю, что мог бы сделать это легко = /

Вот небольшая иллюстрация того, как я хочу это использовать:

#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;
}

Ответы [ 3 ]

11 голосов
/ 15 марта 2012

Используйте std::bind через std::bind1st и std::bind2nd

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

К сожалению, стандарт не помогает для версии с двумя аргументами, и вам нужно написать свой собственный:

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)
             );
1 голос
/ 15 марта 2012

Вы можете связать:

using std::placeholders::_1
int a;
std::for_each(list.begin(), list.end(), std::bind(&Interface::do_something, _1, a));
1 голос
/ 15 марта 2012

См. std::bind1st и std::bind2nd.Они довольно неуклюжи и уродливы в использовании, но если вы настаиваете на том, чтобы использовать только то, что присутствует в C ++ 03, без каких-либо дополнений, то они почти все, что доступно.

Редактировать: когда / еслиМне нужно сделать это, я обычно делаю это с небольшим классом функторов вместо использования std::bind1st и / или std::bind2nd.В конечном счете, это не сильно отличается от того, что они генерируют, но (IMO), как правило, более читабельно.

template<class T>
class invoke_do_something { 
    int value;
public:
    adder(int x) : value(x) {}
    void operator()(T &t) { 
        t.do_something(value);
    }
};

std::for_each(list.begin(), list.end(), invoke_do_something(1));

Однако я считаю, что в большинстве случаев это своего рода пластырь,Это происходит постоянно, используя for_each.Я обычно нахожу, что, подумав, я могу найти более подходящий алгоритм, который часто исключает необходимость чего-либо в этом порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...