преобразование цикла for в std :: for_each - PullRequest
9 голосов
/ 11 июля 2010

У меня есть цикл for:

    std::vector<itemPtr>::iterator it;
    for(it=items.begin(); it!=items.end(); ++it)
    {
        investigators.addToLeaderInventory(*it);
    }

Я бы хотел преобразовать его в нечто вроде этого:

std::for_each(items.begin(), items.end(), investigators.addToLeaderInventory);

Однако эта строка не компилируется.g ++ показывает мне это:

error: no matching function for call to
‘for_each(__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*,
std::vector<std::tr1::shared_ptr<yarl::item::Item>,  
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >,  
__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*,  
std::vector<std::tr1::shared_ptr<yarl::item::Item>,   
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >, <unresolved overloaded
function type>)’  
/usr/include/c++/4.4/bits/stl_algo.h:4194: note: candidates are: _Funct  
std::for_each(_IIter, _IIter, _Funct) [with _IIter =  
__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<yarl::item::Item>*,   
std::vector<std::tr1::shared_ptr<yarl::item::Item>,   
std::allocator<std::tr1::shared_ptr<yarl::item::Item> > > >, _Funct = void 
(yarl::party::Party::*)(yarl::itemPtr)]

Трудно читать, если не сказать больше.Я думаю, что решение довольно простое, но я не могу понять, на что жалуется g ++.Подпись investigators.addToLeaderInventory() такова:

void ClassName::addToLeaderInventory(itemPtr item);

, которая должна работать с for_each, не так ли?Что я должен изменить?

Ответы [ 3 ]

8 голосов
/ 11 июля 2010

for_each принимает вызываемый объект некоторого вида. Чтобы вызвать функцию-член для другого объекта, вам нужно использовать mem_fun, который оборачивает функцию-член так, чтобы ее можно было вызывать как обычную функцию, а затем необходимо привязать ее к экземпляру объекта, на котором она должна быть вызывается с помощью bind1st:

std::for_each(items.begin(), items.end(), 
    std::bind1st(std::mem_fun(&ClassName::add), &investigators));

Другой вариант - использовать более современный bind, который ваша реализация может предоставить в пространстве имен std или std::tr1 (если этого не произойдет, вы можете использовать реализацию из Boost ):

using std::placeholders::_1;

std::for_each(items.begin(), items.end(), 
    std::bind(&ClassName::add, &investigators, _1);
2 голосов
/ 11 июля 2010

C ++ не может связать объект и метод вместе в одну вызываемую «функцию».Вы должны сделать привязку явно, либо через объект с пользовательским operator() ...

class AddToLeaderInventory {
public:
    AddToLeaderInventory(party::Party& party) : party_(party) { }

    void operator()(item::Item& i) { party_.addToLeaderInventory(i); }

private:
    party::Party& party_;
};
...
std::for_each(items.begin(), items.end(), AddToLeaderInventory(investigators));

... или с помощью библиотеки, такой как Boost.Bind.

1 голос
/ 11 июля 2010

Если у вас есть лямбды, то вы можете сделать

for_each(items.begin(), items.end(), 
         [&](const ItemPtr& it) {investigators.addToLeaderInventory(it);});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...