2010-09-01 18 views
11

¿C++ 11 proporciona delegados?Delegado en C++ 11

Si no es así, ¿cuál es la mejor (más eficiente) forma de hacer algo similar en C++? Boost.Signals? FastDelegate? ¿Algo más?

+0

Cuál es incorrecto con los punteros de función? – alternative

+0

No puedo usarlo con el método de clase:/ – dot222

+0

sí, puedes http: //www.parashift.com/C++ - faq-lite/punteros-a-miembros.html pero probablemente hay cosas mejores para usar, p. Las funciones de C++ no necesitan ser métodos, o puedes convertir la clase en un functor –

Respuesta

14

Usted puede obtener la semántica delegado como el uso de bind para unirse a una función miembro de una instancia de clase:

#include <functional> 

struct C 
{ 
    void Foo(int) { } 
}; 

void Bar(std::function<void(int)> func) 
{ 
    func(42); // calls obj.Foo(42) 
} 

int main() 
{ 
    using namespace std::placeholders; 

    C obj; 
    Bar(std::bind(&C::Foo, obj, _1)); 
} 

En este ejemplo, Bar() toma cualquier cosa que tenga un solo int parámetros y que devuelve void.

En main(), vinculamos un puntero a la función de miembro C::Foo a la instancia de C con el nombre obj. Esto nos da un objeto que se puede llamar con un solo parámetro int y que devuelve void.

Llamamos Bar() con este objeto y Bar() hace la llamada obj.Foo(42).

+0

+1, o simplemente puedes convertir C en un funtor. –

+0

@jk: solo algunas veces Obviamente en este caso podrías, pero no tengo muchas clases en mi aplicación que tengan solo una función miembro :-) –

-1

El mecanismo C siempre ha sido puntero a la función & bastón (excepto qsort() y bsearch() que no tomó un bastón).

Así que uno siempre pasaría el objeto de clase como testigo.

ej .:

class tp { 
    public: 
     tp() { n = 0; } 
     void m(int z) { printf("%d is %d\n", n++, z++); } 
     int n; 
}; 

void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton) 
{ 
    for (int i = 0; i < cnt; i++) 
     handler(opx[itm], baton); 
} 

/* You would need to provide this stub -- potentially templateable */ 
void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); } 

/* used like so: */ 
int main() 
{ 
    int array[7]; 

    //... 
    tp cx; 
    higher_func(array, 7, translate_baton, &cx); 
} 
+5

Esta pregunta no es sobre C: el mecanismo C está disponible en C++ pero eso no lo hace la mejor opción. –

+0

Trabajo mucho con los delegados en .NET y créanme de esta manera me habría ahorrado problemas en el camino de los delegados que al revés. – Joshua

0

No necesariamente tienen que esperar para C++ 0x. Puede implementar Delegados casi tan bien en el estándar actual C++ 03. Simplemente tiene que sobrecargar el operador(), de modo que puede llamar al MyObjectFunctor functor; functor(); y dado que el funtor es un objeto, puede pasarlo como un delegado/objeto a funciones;

La versión actual de la STL define el encabezado <algorithm> que proporciona funciones listas para ser utilizadas con Functors/Lambdas/Delegates.

ejemplo simple de un functor.

struct FunctorDelegate 
{ 
    // as so to delegate as a function that takes an int input 
    void operator()(int) 
    { 
     // do what I want 
    } 
}; 

int main() 
{ 
    //... do some stuffs with an std::vector<int> aRange; 
    FunctorDelegate functor; 
    std::for_each(aRange.begin(), arange.end(), functor); 
} 
+0

Lo que los delegados pueden hacer es la capacidad de almacenar, por ejemplo, 'int A :: func1 (int, int)' o 'int B :: func2 (int, int)' en una variable (digamos 'f'), entonces que podría llamarse como 'int v = f (a, 12, 34);' o 'int v2 = f (b, 42, 24);'. En su ejemplo, se podría llamar al funtor, pero no se puede tratar como una abstracción de la función tipo 'void (int)'. –

2

No necesita C++ 0x. en <functional> tiene bind1stbind2ndmem_fun y mem_fun_ref. También tiene Boost.Bind que generaliza todas las funciones anteriores (IIRC).

Yendo de la memoria ...

vector<Foo> foo = makeVector(); 
vector<Foo*> foop = makeVectorP(); 
vector<Bar> bar1,bar2,bar3,bar4; 
transform(foo.begin(), foo.end(), back_inserter(bar1), mem_fun_ref(&Foo::getBar)); 
transform(foop.begin(), foop.end(), back_inserter(bar2), mem_fun(&Foo::getBar)); 
transform(foo.begin(), foo.end(), back_inserter(bar3), bind1st(&bar_from_foo)); 
transform(foo.begin(), foo.end(), back_inserter(bar4), boost::bind(&bar_from_foo, _1)); 
+6

bind1st, bind2nd, mem_fun y mem_fun_ref están en desuso en C++ 11. –

1

Aunque std::function funciona muy bien, me gustaría señalar esta bonita pieza de código delegado, por escrito here (incluyendo ejemplo de uso!). A continuación de las referencias y respuestas, puede leer todo sobre cómo se construye esta clase Delegate y por qué puede ser más rápido que std::function.

Tenga en cuenta también que mi pregunta here para un problema que me encontré con él en VS 2015.