2010-07-11 12 views
9

Tengo este bucle for:convertir un bucle para un std :: for_each

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

me gustaría convertirlo en algo como esto:

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

Sin embargo, ese la línea no compila. g ++ me muestra esto:

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)] 

Difícil de leer, por decir lo menos. Me imagino que la solución es bastante simple, pero no puedo entender de qué se queja BG. La firma de investigators.addToLeaderInventory() es la siguiente:

void ClassName::addToLeaderInventory(itemPtr item); 

que debe funcionar con una for_each, no? ¿Qué debería cambiar?

+1

si usted está dispuesto a impulsar el uso, hay una excelente aplicación foreach, BOOST_FOREACH – Anycorn

Respuesta

8

for_each toma una entidad invocable de algún tipo. Para llamar a una función miembro en otro objeto, necesita usar mem_fun, que envuelve la función miembro para que pueda ser llamada como una función común, luego debe vincularla a la instancia del objeto con la que se debe llamar utilizando bind1st:

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

Otra opción es utilizar la más moderna bind, que su aplicación puede proporcionar en el std o std::tr1 espacio de nombres (si no lo hace, puede utilizar the implementation from Boost):

using std::placeholders::_1; 

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

Esto es lo que estaba buscando. Gracias. – Max

2

C++ no puede unir un objeto y un método en una sola "función" invocable. Que tiene que hacer la unión de forma explícita, ya sea a través de un objeto con una costumbre 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)); 

... o el uso de una biblioteca como Boost.Bind.

1

Si tienes lambdas entonces usted podría hacer

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