7

He estado aprendiendo D, y estoy particularmente emocionado por sus capacidades de programación genérica. Los delegados son maravillosos, y al parecer se han sustituido por completo miembros de la función triples, por lo que me he quedado atrapado cuando quería implementar algo como lo siguiente:D Analógico a C++ member-function-pointers, no necesariamente delegados

template <typename T> 
void DispatchMethodForAll(std::vector<T*> & container, void (T::* func)(void)) 
{ 
    for(typename std::vector<T*>::iterator it = container.begin(); it != container.end(); ++it) 
     (*it)->*func(); 
} 

De acuerdo con lo que he aprendido de los punteros de función y delegados en Re , es que ninguno de ellos puede hacer esto, ya que los punteros de funciones solo pueden declararse para funciones globales, y los delegados tienen que estar vinculados a un objeto, no hay un "delegado parcial" que pueda encontrar. Como se ve aquí, no puedo usar un delegado, ya que no hay un único objeto que pueda vincularse al método que se va a llamar.

Sé que yo podría hacerlo con mixins, y esencialmente hacerlo una macro. Sin embargo, esto realmente no suena como D, y pensé que debería haber "La forma correcta"

+0

¿Necesita esta selección de miembros dinámicos a suceder en tiempo de compilación o debe ser capaz de suceder en tiempo de ejecución? – Mehrdad

+0

Para este caso particular podría ser en tiempo de compilación, pero también tengo curiosidad por ver qué solución para el tiempo de ejecución sería –

Respuesta

6

Aún puede usar un delegado aquí.

void DispatchMethodForAll(T)(T*[] container, void delegate(T*) action) 
{ 
    foreach (it; container) 
     action(it); 
} 

... 

DispatchMethodForAll(container, (Foo* foo) { foo.func(); }); 

Ejemplo: http://www.ideone.com/9HUJa

+0

BTW, creo que esta solución es, más o menos, tal vez con un poco de abstracción, qué a * puntero C++ a método virtual * termina siendo. – BCS

+0

Es casi exactamente eso. Creo que esta es la forma "correcta" de hacerlo, aunque esperaba poder hacerlo sin tener que adaptar una función a un delegado. También tengo curiosidad por ver qué tipo de código escupirá el compilador, porque espero que no genere asignaciones de memoria innecesarias. –

3

se puede tomar una página del std.algorithm para averiguar cómo se hace eso

void DispatchMethodForAll(alias func, T)(T container) 
{ 
    alias unaryFun!func _func 
    foreach (it; container) 
     _func(it); 
} 

por cierto un delegado puede estar unido a una estructura y el compilador puede crear una estructura personalizada a partir de variables locales (stack asignado) y definir un delegado en ese

esto ocurre con

void foo(){ 
    int[] array; 
    int i=0; 
    void bar(int a){ 
     i+=a; 
    } 
    void DispatchMethodForAll(&bar)(array); 
    writeln(i);//prints the sum of array 
} 

bar es un delegado unido a una estructura con (al menos) un miembro de i de tipo int de los cuales la variable local i es un alias

+0

Me podría estar perdiendo algo sobre unaryFun, pero no veo cómo se sabe que func es una función miembro de T. –

+0

@Ramon, no es así, ¿eso importa? También en este caso unaryFun no hace absolutamente nada. func solo tiene un alias a _func. –

+0

Solo para tener en cuenta: esta es una función de solo tiempo de compilación. – Mehrdad