将for循环转换为std :: for_each

时间:2010-07-11 00:51:22

标签: c++ foreach

我有这个循环:

    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 个答案:

答案 0 :(得分:8)

for_each需要某种可调用的实体。为了在另一个对象上调用成员函数,你需要使用mem_fun,它包装成员函数,以便可以像普通函数一样调用它,然后你需要将它绑定到它上面的对象实例应该使用bind1st

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

另一种选择是使用更现代的bind,您的实现可能会在stdstd::tr1命名空间中提供(如果没有,您可以使用{{3} }):

using std::placeholders::_1;

std::for_each(items.begin(), items.end(), 
    std::bind(&ClassName::add, &investigators, _1);

答案 1 :(得分:2)

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等库。

答案 2 :(得分:1)

如果你有lambdas那么你可以做

for_each(items.begin(), items.end(), 
         [&](const ItemPtr& it) {investigators.addToLeaderInventory(it);});