I've got this for loop:
std::vector<itemPtr>::iterator it;
for(it=items.begin(); it!=items.end(); ++it)
{
investigators.addToLeaderInventory(*it);
}
I'd like to convert it to something like this:
std::for_each(items.begin(), items.end(), investigators.addToLeaderInventory);
However, that line doesn't compile. g++ shows me this:
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)]
Hard to read, to say the least. I imagine the solution is pretty simple, but I can't figure out what g++ is complaining about. The signature of investigators.addToLeaderInventory()
is this:
void ClassName::addToLeaderInventory(itemPtr item);
which should work with a for_each
, shouldn't it? What should I change?
C++ can't bind an object and a method together into a single callable "function". You have to do the binding explicitly, either via a object with a custom 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));
...or using a library such as Boost.Bind.
for_each
takes a callable entity of some kind. In order to call a member function on another object, you need to use mem_fun
, which wraps the member function so that it can be called like an ordinary function, then you need to bind it to the object instance on which it should be called using bind1st
:
std::for_each(items.begin(), items.end(),
std::bind1st(std::mem_fun(&ClassName::add), &investigators));
Another option is to use the more modern bind
, which your implementation may provide in the std
or std::tr1
namespace (if it doesn't, you can use the implementation from Boost):
using std::placeholders::_1;
std::for_each(items.begin(), items.end(),
std::bind(&ClassName::add, &investigators, _1);
If you have lambdas then you could do
for_each(items.begin(), items.end(),
[&](const ItemPtr& it) {investigators.addToLeaderInventory(it);});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With