2009-03-23 15 views
5

Considere un siguiente código:¿Es posible crear el método call dispatcher en C++?

struct X { 
    void MethodX() { 
    ... 
    } 
}; 

struct Y { 
    void MethodY() { 
    ... 
    } 
}; 

void test() { 
    X x; 
    Y y; 
    Dispatcher d; 
    d.Register("x", x, &X::MethodX); 
    d.Register("y", y, &Y::MethodY); 
    d.Call("x"); 
    d.Call("y"); 
} 

La cuestión es cómo implementar Dispatcher. No me importa que X e Y puedan heredar de algo, pero Dispatcher debería permitir más clientes (no solo X e Y). Y me gustaría evitar los punteros void * si es posible :)

+0

¿tiene acceso a la biblioteca de impulso? –

+0

¿Podría aclarar "El problema es el tipo de estructura de datos que mantiene los punteros o funtores del método". –

+0

Estaba intentando implementar esto con la plantilla std :: tr1 :: mem_fun. Pero el tipo de resultado tenía dentro del tipo de parámetros. Entonces no pude hacer un vector heterogéneo que lo contenga. –

Respuesta

5

Eche un vistazo a boost::function, hace esto.

+0

No resuelvo el problema. Eche un vistazo a la pregunta actualizada. –

+0

Quizás sí. Estoy investigando :) –

1

Tengo una respuesta similar here, pero la respuesta de Mykola está más cerca de lo que necesita.

1

Tome un vistazo a este artículo:

http://www.oopweb.com/CPP/Documents/FunctionPointers/Volume/CCPP/functor/functor.html

Implementa un funtor plantilla basada en C++. void * se usa debajo de los cofres, pero es seguro para todos los tipos porque está envuelto por funciones de plantilla que crean y desenvuelven el vacío *. Haría que implementar esto sea fácil. Es compatible con una variedad de estilos de llamada que los punteros de método sencillo no (por ejemplo, puede pasar una función devolviendo algo como un functor que devuelve vacío e ignora automáticamente el valor de retorno)

2

Para evitar aumentar el uso e implementar uno propio, puede echar un vistazo al libro http://en.wikipedia.org/wiki/Modern_C%2B%2B_Design

Hay una biblioteca Loki se describe en el libro con una buena explicación de cómo hacer su propio lo suficientemente inteligente como para su necesidad funtor.

class Dispather 
{ 
public: 
    typedef boost::function< void (void) > FunctionT; 

    void Register(const std::string& name, FunctionT function) 
    { 
     registered_[ name ] = function; 
    } 

    void Call(const std::string& name) 
    { 
     RegisterdFunctionsT::const_iterator it = 
      registered_.find(name); 

     if (it == registered_.end()) 
      throw std::logic_error("Function is not registered"); 

     (it->second)(); 
    } 

private: 
    typedef std::map< std::string, FunctionT > RegisterdFunctionsT; 
    RegisterdFunctionsT registered_; 

}; 

int main() 
{ 
    X x; 
    Y y; 

    Dispather d; 
    d.Register("x", boost::bind(&X::MethodX, &x)); 
    d.Register("y", boost::bind(&Y::MethodY, &y)); 

    d.Call("x"); 
    d.Call("y"); 

    return 0; 
} 
+0

Esto se ve genial. ¿Cómo se convierte typeof (& X :: MethodX) en FunctionT? ¿Cómo puedo implementarlo yo mismo y evitar el uso de impulso? –

+0

Para evitar aumentar el uso ... y luego está usando la función boost ::? –

Cuestiones relacionadas