Pregunta

Estoy tratando de usar el algoritmo stl para_each sin proliferar plantillas en todo mi código. std :: for_each desea crear una instancia de la clase MyFunctor por valor, pero no puede hacerlo desde su resumen. He creado una clase de adaptador de funtor que pasa un puntero y luego la elimina cuando es apropiado.

Mi pregunta:

¿El STL o Boost ya tienen una clase de adaptador de este tipo? ¡No quiero tener que reinventar la rueda!

 struct MyFunctor  {
     virtual ~MyFunctor() {}
     virtual void operator()(int a) = 0; 
 }

 namespace {
     template<typename FunctorType, typename OperandType> struct
 FunctorAdapter
     {
         FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
         void operator()(OperandType& subject)
         {
             (*mFunctor)(subject);
         }

         FunctorType* mFunctor;
     }; }

 void applyToAll(MyFunctor &f) {
     FunctorHelper<MyFunctor, int> tmp(&f);
     std::for_each(myvector.begin(), myvector.end(), tmp); }

Saludos,

Dave

¿Fue útil?

Solución

tr1 :: ref puede ayudarlo aquí --- está destinado a ser un envoltorio de referencia para que pueda pasar objetos normales por referencia a objetos de enlace o función (incluso abstractos) por referencia a algoritmos estándar.

// requires TR1 support from your compiler / standard library implementation
#include <functional>

void applyToAll(MyFunctor &f) {
    std::for_each(
        myvector.begin(), 
        myvector.end(), 
        std::tr1::ref(f) 
    ); 
}

Sin embargo, TENGA EN CUENTA que los compiladores sin soporte para decltype PUEDEN rechazar el paso de una referencia a un tipo abstracto ... por lo que este código no se compilará hasta que obtenga soporte para C ++ 0x.

Otros consejos

Puede usar los adaptadores de función (y sus calces) de funcional .

#include <functional>

using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );

Si su contenedor contiene punteros a objetos, use mem_fun_ptr , de lo contrario use mem_fun . Junto a estos, hay envoltorios para funciones miembro que toman 1 argumento: mem_fun1_ptr y mem_fun1 .

@Evan: de hecho, puedes llamar a la función miembro con el mismo argumento para cada objeto. El primer argumento de los envoltorios mem_fun1 es el puntero this , el segundo es el argumento de la función miembro:

for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );

Con más argumentos, se vuelve más legible crear un bucle, o crear un functor personalizado que tenga constantes variables de miembros que representan los argumentos.

Parece que podría beneficiarse de Boost :: Function .

Si recuerdo correctamente, también es una biblioteca de solo encabezado, por lo que es fácil hacerlo funcionar.

¿Qué hay de olvidar todo el envoltorio del puntero del funtor, y en su lugar usar bind (functor_pointer, mem_fun1 (& amp; MyFunctor :: operator ());  como el functor? de esa manera, no tiene que preocuparse por administrar la copia de ninguna forma o forma.

Basándose en la respuesta de @xtofl, ya que la matriz contiene int's y no " this " Punteros, creo que el encantamiento correcto es

class MyClass
{
  virtual void process(int number) = 0;
};
MyClass *instance = ...;

for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );

La única diferencia frente al código de @xtofl es binder1st en lugar de binder2nd. binder2nd le permite pasar el mismo número a varios " este " punteros binder1st le permite pasar varios números a uno " este " puntero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top