Home

[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?

Thanks,
Andre

previous
next

Re: Should I use pointer inside container?
Re: A deque containing different types of objects (with a commonbase class)
Re: Puzzled by "is"
Re: where static objects live in memory.
Re: Adjusting the names of custom exceptions (since raising strings is deprecated)
Fundacja Iskierka
Niechciane i Zapomniane
Pajacyk
Fundacja Avalon
Akogo