[long post warning - lots of (bad?) code ahead...]
On Aug 13, 12:17 am, Ian Collins <ian-n...@hotmail.com> wrote:
int2...@gmail.com wrote:
On Aug 12, 10:44 pm, Ian Collins <ian-n...@hotmail.com> wrote:
int2...@gmail.com wrote:
On Aug 12, 8:56 pm, Ian Collins <ian-n...@hotmail.com> wrote:
Yes, that's exactly what I'd like to do. Except that I need pointers
to member functions, which gets complicated (at least for me). I
can't
come up with a clean setup.
All hints would be appreciated.
Pointers to members of the same class, or different classes?
Same class.
The just change the typedef to be a pointer to member type.
#include <map>
struct X {
void fn() {}
};
X x;
typedef void (X::*Fn)();
std::map<int, Fn> table;
void loader( int n, Fn fn) {
table[n] = fn;
}
void dispatcher( int n ) {
(x.*table[n])();
}
int main() {
loader( 1, &X::fn );
dispatcher( 1 );
}
Ok, so I lied...
I actually do have different classes. Since I'm trying to make this
generic so I can apply the mechanism to various classes. Furthermore,
I'd like something where I can apply the mechanism to a base class,
but also use it in a derived class.
So here's what I came up with:
---------- FILE: dynamicdispatch.h ----------
Link to formatted source code here:
http://ironcreek.net/code/dynamicdispatch.h
#ifndef DYNAMICDISPATCH_H
#define DYNAMICDISPATCH_H
#include <map>
#define REGISTERMSG(msg, class, func) RegisterHandler( msg, new
MsgHandler<class>( this, &class::func ));
class IMsgHandler
{
public:
virtual unsigned Handle( unsigned, unsigned ) = 0;
};
template <typename T>
class MsgHandler : public IMsgHandler
{
public:
typedef unsigned (T::*HandlerFunc)( unsigned, unsigned );
MsgHandler( T* pobj, HandlerFunc handler )
: obj( pobj )
, func( handler )
{
}
unsigned Handle( unsigned p1, unsigned p2 )
{
return (obj->*func)( p1, p2 );
}
protected:
T *obj;
HandlerFunc func;
};
class DynamicDispatch
{
public:
~DynamicDispatch()
{
std::map<unsigned, IMsgHandler*>::iterator ii;
for( ii = func_map.begin(); ii != func_map.end(); ++ii )
delete ii->second;
}
void RegisterHandler( unsigned msg, IMsgHandler *p_handler )
{
func_map[ msg ] = p_handler;
}
unsigned HandleMessage( unsigned msg, unsigned p1, unsigned p2 )
{
std::map<unsigned, IMsgHandler*>::iterator ii =
func_map.find( msg );
if ( ii != func_map.end() )
return ii->second->Handle( p1, p2 );
return 0;
}
protected:
std::map<unsigned, IMsgHandler*> func_map;
};
#endif
---------- FILE: funcmap.cpp ----------
Link to formatted source code here:
http://ironcreek.net/code/funcmap.cpp
#include <iostream>
#include "dynamicdispatch.h"
const unsigned FIRST_EVENT = 1000;
const unsigned SECOND_EVENT = 2000;
const unsigned THIRD_EVENT = 3000;
class Dialog : public DynamicDispatch
{
public:
Dialog()
{
REGISTERMSG( THIRD_EVENT, Dialog, MyEvent );
}
unsigned MyEvent( unsigned, unsigned )
{
std::cout << "Dialog::MyEvent()\n";
return 0;
}
};
class MyDlg : public Dialog
{
public:
MyDlg()
{
REGISTERMSG( FIRST_EVENT, MyDlg, Func1 );
REGISTERMSG( SECOND_EVENT, MyDlg, Func2 );
}
unsigned Func1( unsigned p1, unsigned p2 )
{
std::cout << "MyDlg::Func1() p1=" << p1 << " p2=" << p2 <<
"\n";
return 0;
}
unsigned Func2( unsigned p1, unsigned p2 )
{
std::cout << "MyDlg::Func2() p1=" << p1 << " p2=" << p2 <<
"\n";
return 0;
}
void Test()
{
HandleMessage( FIRST_EVENT, 11, 22 );
HandleMessage( SECOND_EVENT, 11, 22 );
HandleMessage( THIRD_EVENT, 11, 22 );
}
};
int main()
{
MyDlg dlg;
dlg.Test();
}
Now, I am _reasonably_ happy with that code - except for one thing.
The macro (REGISTERMSG) I use to register the message handlers. But
the alternative syntax that the macro masks, is a bit hard on the eye
if repeated often...
So what do you guys think about this code and are there any
suggestions to make the REGISTERMSG() functionality not a macro, but
still as clean as possible?
kludge. You thought if...else was ugly and repetitive but this isn't?