Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create method call dispatcher in C++?

Consider a following code:

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");
}

The question is how to implement Dispatcher. I don't mind X and Y may inheriting from something, but Dispatcher should allow further clients (not only X and Y). And I would like to avoid void* pointers if possible :)

like image 284
Łukasz Lew Avatar asked Mar 23 '09 11:03

Łukasz Lew


3 Answers

Take a look at boost::function, it does this.

like image 65
Assaf Lavie Avatar answered Nov 11 '22 19:11

Assaf Lavie


To avoid boost usage and implement your own you can take a look at the book http://en.wikipedia.org/wiki/Modern_C%2B%2B_Design

There is a Loki library described in the book with a good explanation how to make your own smart enough for your need functor.

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;
}
like image 22
Mykola Golubyev Avatar answered Nov 11 '22 20:11

Mykola Golubyev


Take a look at this paper:

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

It implements a template based functor in C++. void* is used under the hoods, but it's all type-safe because it's wrapped by template functions that create and unwrap the void*. It would make implementing this easy. It support a variety of call styles that plain method pointers don't (e.g. you can pass a function returning something as a functor returning void and it automatically ignores the return value)

like image 1
Lou Franco Avatar answered Nov 11 '22 21:11

Lou Franco