Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Re: std::map of pointers to member functions (http://www.velocityreviews.com/forums/t275983-re-std-map-of-pointers-to-member-functions.html)

Victor Bazarov 07-24-2003 04:36 AM

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



Jonathan Mcdougall 07-24-2003 11:06 PM

Re: std::map of pointers to member functions
 
>> 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



All times are GMT. The time now is 09:09 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.