| Topic: |
DEVELOP > c-Plus-Plus |
| User: |
"Victor Bazarov" |
| Date: |
23 Jul 2003 11:36:55 PM |
| Object: |
Re: std::map of pointers to member functions |
"Jonathan Mcdougall" <DELjonathanmcdougall@yahoo.ca> wrote...
To make a long story short, I need to associate events with pointers
to functions. The first idea which came to my mind was
enum Event
{
clicked,
moved
};
typedef void (*Handler)(int);
void my_handler(int)
{
std::cout << "in my handler";
}
int main()
{
std::map<Event, Handler> handlers;
handlers.insert(std::make_pair(clicked, &my_handler));
if ( event_triggered(clicked) )
(handlers[clicked])( /*whatever*/ );
}
I hope this makes sense.
Now, the thing is, I need to include member functions too, so I came
up with that :
template<class Object, class Function> class Handler
{
private:
Object obj_;
Function fun_;
public:
template<class Object, class Function>
Handler(Object obj, Function fun)
: obj_(obj),
fun_(fun)
{
}
void operator()(int whatever)
{
((*obj_).*fun_)(whatever);
}
};
But now I am stuck with the std::map, since it cannot accept templates
(as I understand).
Could anybody show me a way of acheiving the equivalent results?
Nothing can accept templates. Everything has to eventually boil down
to become a concrete class or function. Since you cannot store different
instantiations of your template class 'Handler' in the same map, you need
to play the polymorphic card:
#include <map>
using std::map;
enum Event { Clicked, Moved };
class BaseHandler {
public:
~BaseHandler() {}
virtual void operator()(int whatever) = 0;
};
template<class Object> class Handler
: public BaseHandler {
public:
typedef void (Object::*Function)(int);
private:
Object* obj_;
Function fun_;
public:
Handler(Object* obj, Function fun)
: obj_(obj), fun_(fun)
{
}
void operator()(int whatever)
{
(obj_->*fun_)(whatever);
}
};
template<class Object> Handler<Object>*
makeHandler(Object* obj,
typename Handler<Object>::Function fun) {
return new Handler<Object>(obj, fun);
}
class ClickHandler {
public:
void doit(int);
};
int main() {
map<Event, BaseHandler*> myhandlers;
ClickHandler cH;
myhandlers[Clicked] = makeHandler(&cH, &ClickHandler::doit);
// use it and then _delete_ every entry in the map
}
I haven't got this to execute, besides, there is no code to use the
map, but you should get the idea...
Victor
.
|
|
| User: "Jonathan Mcdougall" |
|
| Title: Re: std::map of pointers to member functions |
24 Jul 2003 06:06:44 PM |
|
|
But now I am stuck with the std::map, since it cannot accept templates
(as I understand).
Could anybody show me a way of acheiving the equivalent results?
Nothing can accept templates. Everything has to eventually boil down
to become a concrete class or function.
It makes sense, I still have some difficulties understanding, or
visualizing, templates.
Since you cannot store different
instantiations of your template class 'Handler' in the same map, you need
to play the polymorphic card:
#include <map>
using std::map;
enum Event { Clicked, Moved };
class BaseHandler {
public:
~BaseHandler() {}
virtual void operator()(int whatever) = 0;
};
template<class Object> class Handler
: public BaseHandler {
public:
typedef void (Object::*Function)(int);
private:
Object* obj_;
Function fun_;
public:
Handler(Object* obj, Function fun)
: obj_(obj), fun_(fun)
{
}
void operator()(int whatever)
{
(obj_->*fun_)(whatever);
}
};
template<class Object> Handler<Object>*
makeHandler(Object* obj,
typename Handler<Object>::Function fun) {
return new Handler<Object>(obj, fun);
}
class ClickHandler {
public:
void doit(int);
};
int main() {
map<Event, BaseHandler*> myhandlers;
ClickHandler cH;
myhandlers[Clicked] = makeHandler(&cH, &ClickHandler::doit);
// use it and then _delete_ every entry in the map
}
Wow.
It took me a while to integrate it (since I am not very good with
templates), but it works like a charm, as your solutions always do.
Thank you,
Jonathan
.
|
|
|
|

|
Related Articles |
|
|