¿Una forma más fácil de hacer devoluciones de llamada para vectores (o quizás algo más en el STL)? C ++

Estoy haciendo un simple juego de simulación de crimen.

A lo largo de ello sigo haciendo lo mismo una y otra vez:

// vector drugSack; for (unsigned int i = 0; i drugSack.size(); i++) this->sell(drugSack[i]); 

Sólo un ejemplo. Odio tener todos estos bucles por todos lados omg QQ, de todos modos para hacer algo como:

 drugSack->DoForAll((void*)myCallBack); 

No estoy bien versado en el STL.

Es hora de empezar a conocer los algoritmos de stl:

 #include  ... std::for_each( drugSack.begin(), drugSack.end(), std::bind1st( std::mem_fun_ptr( &ThisClass::Sell ), this ) ); 

La idea es crear un objeto, llamado “functor”, que pueda realizar una determinada acción para cada uno de los elementos en el rango drugSack.begin(), drugSack.end() .

Este functor se puede crear utilizando construcciones stl como mem_fun_ptr , lo que resulta en un funtor que toma un ThisClass* y un Drug* , y una envoltura alrededor que lo sustituirá / unirá a la Class* para this .

Honestamente, C ++ actualmente es bastante malo en este tipo de cosas. Definitivamente puede hacerlo, como se describe en la respuesta de xtofl, pero a menudo es muy torpe.

Boost tiene una macro para cada uno que es bastante conveniente:

 #include  #define foreach BOOST_FOREACH // ... foreach(Drug* d, drugSack) { sell(d); } 

O tal vez Boost.Bind , aunque esto es un poco más complejo, se lee muy bien para su caso:

 #include  // ... // ThisClass refers to whatever class this method is in std::for_each(drugSack.begin(), drugSack.end(), boost::bind(&ThisClass::sell, this, _1)); 

Bind creará un functor que llama a la función miembro de ThisClass , sell , en la instancia de la clase apuntada por this , y reemplazará _1 con el argumento que obtiene de for_each .

El método más general es con lambda. Boost tiene una biblioteca lambda . No incluiré muestras aquí porque para su caso específico, el enlace de refuerzo funciona, y la lambda sería el mismo código. Dicho esto, los lamba pueden hacer mucho más! Básicamente, crean funciones in situ (implementadas como funtores), pero son mucho más complejas de aprender.

Tanto para-cada como para bind son mucho más limpios que los métodos “estándar” de C ++, en mi opinión. Por el momento, recomiendo, en orden: para cada, enlace, estándar C ++, lambda.

En C ++ 0x, el próximo estándar de C ++, todo esto volverá a estar bien con el soporte lambda incorporado:

 std::for_each(drugSack.begin(), drugSack.end(), [this](DrugSack* d){ sell(d); }); 

O la nueva gama basada en bucles:

 for(DrugSack* d : drugSack) { sell(d); } 

Pero debemos esperar un par de años antes de que esta sea una opción. 🙁 Además, creo que el bucle for basado en rango es lo más fácil de leer. Por eso recomiendo impulsar para cada uno, porque imita este comportamiento y la syntax (en su mayoría).

Además, totalmente sin relación: el estilo donde se incluye this-> antes de que todo sea, en mi experiencia, generalmente considerado una mala práctica. El comstackdor lo hará por usted, todo lo que está haciendo es saturar su código e introducir la posibilidad de cometer errores. Las cosas se leen mucho mejor sin ella.

Podría usar std :: for_each desde la STL que aplica una función a un rango. Consulte la siguiente descripción: http://www.cplusplus.com/reference/algorithm/for_each/ .

También necesitarás usar std :: mem_fun o std :: mem_fun_ptr para obtener la función miembro de tu clase.

Para casos más avanzados, eche un vistazo a Boost Bind que proporciona un enlace avanzado para crear objetos de función.

Para el caso simple de hacer un bucle a través de un contenedor completo, solo escribo el bucle. Desafortunadamente, tiene mucho aliento, pero no es propenso a cometer errores si siempre lo escribe de la misma manera. Siempre escribo estos bucles de la siguiente manera:

 Container c; for (Container::iterator i = c.begin(), end = c.end(); i != end; ++i) ... 

(o const_iterator cuando corresponda).

Puedes probar BOOST_FOREACH como alternativa.

Bueno, primero estoy confundido: ¿qué sell ? ¿Está destinado a ser una función miembro de alguna clase? Necesitas hacer que DrugSack sea esa clase, en cuyo caso puedes hacer algo como lo siguiente:

Algo como for_each para iterar sobre drugSack , combinado con mem_fun para obtener sell :

 for_each(drugSack.begin(), drugSack.end(), mem_fun(&Drug::sell)) 

Si vender es solo una función ordinaria, puede ponerlo en el tercer argumento de for_each.