Как использовать std :: for_each? - PullRequest
1 голос
/ 15 марта 2012

Можно ли использовать std :: for_each или еще что-нибудь подобное?

#include <list>
#include <algorithm>

// Class declaration
//
struct Interface
{
   virtual void run() = 0;
};

struct A : public Interface
{
   void run() { std::cout << "I run class A" << std::endl; }
};

struct B : public Interface
{
   void run() { std::cout << "I run class B" << std::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);

   // Then execute a func with for_each without recreate a func which call Interface::run() 
   std::for_each(list.begin(), list.end(), run);

   return 0;
}

Редактировать: Мой вопрос таков: как я могу вызывать каждую функцию-член run () внутри цикла, используя алгоритм или, проще, способ C ++ без использования итераторов ...

Ответы [ 4 ]

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

Вы можете сделать это, используя std::mem_fun:

std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::run));
3 голосов
/ 15 марта 2012

Вероятно, самый простой способ - использовать лямбда-функцию:

boost::for_each(list, [](Interface* i){ i->run(); });

Другие опции включают в себя:

boost::for_each(list | boost::adaptors::indirected, std::mem_fn(&Interface::run));

и

boost::for_each(
    list | boost::adaptors::indirected,
    std::bind(&Interface::run, std::placeholders::_1));
1 голос
/ 15 марта 2012

Взяв пример Мэтта, но сделав его универсальным:

class wrapper : public std::unary_function(Interface*, void) {
  void (Interface::*pmf)();
public:
  wrapper(void (Interface::*pmf)()) : pmf(pmf) { }
  operator()(Interface* intf) { intf->*pmf(); }
};

std::for_each(ist.begin(), list.end(), custom_wrapper(&Interface::run));

Если вам нужно поддержать аргументы, выведите из std::binary_function(Interface*, T, void) и сохраните T вместе с pmf

1 голос
/ 15 марта 2012

Нет, вам нужно создать функцию-обертку, которая будет вызывать run() для любого объекта, который передается в него.В C ++ нет такой динамической диспетчеризации, которая позволит вам использовать строку для ссылки на функцию и искать ее во время выполнения - для вызова for_each должна быть одна и только одна функция по одному адресу, а неполиморфная функция.

Вам не нужно создавать функцию-обертку для каждого объекта: у вас просто есть такая, и она вызывается повторно и передается в объект.Затем вы вызываете run () для переданного объекта, и полиморфизм делает все остальное:

void wrapper(Interface* obj)
{
    obj->run();
}

std::for_each(list.begin(), list.end(), wrapper);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...