2012-05-15 15 views
5

yo sólo me encontré crear una clase¿Estoy reinventando la rueda con este método trivial llamada clase de reenvío?

template <typename T> struct invoker { 
    void operator()(T& it) const {it();} 
}; 

para que pudiera pasar una invoker<foo> a algo (que no está bajo mi control), que quiere llamar invoker<foo>::operator()(foo&) en él en varias ocasiones con diferentes foo casos, para conseguir que se reenviar esas llamadas al método foofoo::operator()().

Sé que son solo unas pocas líneas, pero esto parece ser el tipo de cosa que probablemente ya está prevista por el funcional de STL, o boost::bind de alguna manera. Excepto que no puedo ver el truco, si es que hay uno. (Estoy seguro de que no soy la primera persona en usar algo muy parecido a esto: ¿tiene un nombre?)

+1

creo que C++ 11 tiene algo para esto también – pyCthon

+1

Por ahora estoy en g ++ 4.4.5; No creo que g ++ haya obtenido lambdas hasta 4.5. Curioso de ver una solución lambda si uno está publicado; Puedo vivir con mi clase de invoker hasta una actualización de la versión de g ++. – timday

+0

¿Por qué no llamarías 'foo :: operator()' directamente? Quiero decir, la clase que llama a 'invoker :: operator()' tiene que hacer algo como 'some_invoker (some_foo);', mientras que podría llamarlo así: 'some_foo();'. Está agregando una capa innecesaria de indirección. – mfontanini

Respuesta

5

Sí, estás reinventando la rueda. std :: mem_fun_ref hace lo que quieres.

std::vector<foo> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun_ref(&foo::operator())); 

alternativa:

std::vector<foo*> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun(&foo::operator())); 

No tener que meterse con si el parámetro es es una gran ventaja PTR o no de impulso :: mem_fn.

Sin embargo, es mucho más complejo que eso y empiezas a tener problemas con los encuadernadores C++ 03 y necesitas algo más expresivo como boost.bind.

+4

Solo quería señalar que 'std :: mem_fun' y' std :: mem_fun_ref' están en desuso para 'std :: mem_fn' en C++ 11. –

6

Bueno, se puede utilizar std::bind, probablemente boost::bind así lograr el mismo comportamiento:

#include <string> 
#include <iostream> 
#include <functional> 

struct foo { 
    void operator()() { 
     std::cout << "Hallo, im at addr: " << std::hex << this << std::endl; 
    } 
}; 

int main() { 
    std::function<void(foo*)> fun = std::bind(&foo::operator(), std::placeholders::_1); 
    foo f1, f2; 
    fun(&f1); 
    fun(&f2); 
} 

Salidas:

Hallo, im at addr: 0xbffc396a 
Hallo, im at addr: 0xbffc3969 

Si utiliza una clase de plantilla para el tipo de argumento, que puede tener la misma behvaiour sin reinventar la rueda.

Editar: Eddie el Loco como señaló, sólo puede utilizar boost::mem_fn o std::mem_fn:

std::function<void(foo*)> fun = std::mem_fn(&foo::operator()); 

En lugar de bind.

+1

En realidad, no necesita enlazar aquí y puede valer la pena omitirlo. Bind tiene que pasar por un sistema de conversión de argumentos para fusionar las dos listas de argumentos e invocar al objetivo invocable. boost :: mem_fn hará el truco y en realidad bind() para los punteros de miembro lo usa. –

+0

@CrazyEddie, bien, he usado 'mem_fn' hace algún tiempo, pero lo olvidé por completo. Edité mi respuesta: D – mfontanini

+0

OK, este es exactamente el tipo de cosa que estaba buscando gracias; es obvio cuando lo ves, pero de alguna forma me había convencido a mí mismo (demasiado tarde) de que, dado que el método foo que me interesaba no tenía argumentos, no había ningún rol para un _ marcador de posición ... tan equivocado. – timday

Cuestiones relacionadas