Funtores polimórficos en std :: for_each
-
03-07-2019 - |
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
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.
¿Por qué no usar BOOST_FOREACH?
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.