[wx-dev] Template based wxEvtHandler::Connect feature request/suggestion

Brian Vanderburg II BrianVanderburg2 at aim.com
Fri Jul 25 04:12:19 PDT 2008


Vadim Zeitlin wrote:
> On Wed, 23 Jul 2008 22:18:02 -0400 Brian Vanderburg II <BrianVanderburg2 at aim.com> wrote:
>
> BVI> > BVI> Then it would be connected in user code as:
> BVI> > BVI> 
> BVI> > BVI> ConnectMember<wxEVT_PAINT>(id, &MyClass::OnPaint);
> BVI> >
> BVI> >  This still requires an object, doesn't it? I don't see the difference with
> BVI> > the above version to be honest.
> BVI> >   
> BVI> Changing wxEVT_PAINT to a class, the version above required an instance 
> BVI> of wxEVT_PAINT since it was receiving it as an argument:
> BVI> 
> BVI> Connect(int id, E type, ...) -> Connect(myobj->GetId(), wxEVT_PAINT(), ...)
> BVI> 
> BVI> You have to pass wxEVT_PAINT() instead of just wxEVT_PAINT
> BVI> 
> BVI> The second version does not receive E as an argument so it doesn't need 
> BVI> an instance of wxEVT_PAINT, it only needs to be told the type:
> BVI> 
> BVI> Connect<wxEVT_PAINT>(myobj->GetId(), ...)
>
>  Ok, this syntax might be better (although opinions could vary and
> explicitly selecting the template function specialization like this is
> definitely not supported by VC6).
>
>  There is still the problem of how to do anything like this without
> breaking all the existing code defining the custom events. My idea with
> specializing some wxEventHandlerType template for the wxEVT_XXX values
> assumed that we'd be able to rely on default template definition (using
> unsafe wxEvent) for the user-defined types. But with your version I really
> don't see what are we going to do about it...
>   
I was trying to figure some way that, for instance 
wxEventHandlerType<1>::EventObjectType would match somehow for whatever 
event 1, then wxEventHandlerType<wxEVT_PAINT>::EventObjectType woudl be 
wxPaintEvent, etc is, etc.  But, since the type value is not known at 
compile time but is generated at runtime with wxNewEventType, can it 
still be specialized?  I did some extra reading on templates but I don't 
know if it could be since the definition of the class is dependent on 
the value.

I'm sure a way could be found that could keep the existing syntax but 
somehow provide type checking, I'm just not sure what it would be.

> BVI> class EventHandler
> BVI> {
> BVI> public:
> BVI>     EventHandler() { }
> BVI>     ~EventHandler() { }
> BVI>     
> BVI>     template <typename E>
> BVI>     void ConnectFunction(void (*fn)(typename E::EventObjectType&))
> BVI>     {
> BVI>         Functor* f = new FunctionFunctor<typename E::EventObjectType>(fn);
> BVI>         EventEntry e;
> BVI>         e.type = E::GetEventTypeValue();
> BVI>         e.func = f;
> BVI>         m_connections.push_back(e);
> BVI>     }
> BVI>     
> BVI>     template <typename E, typename C>
> BVI>     void ConnectMember(void (C::*fn)(typename E::EventObjectType&), C* obj)
> BVI>     {
> BVI>         Functor* f = new MemberFunctor<typename E::EventObjectType, C>(fn, obj);
> BVI>         EventEntry e;
> BVI>         e.type = E::GetEventTypeValue();
> BVI>         e.func = f;
> BVI>         m_connections.push_back(e);
> BVI>     }
>
>  We should just call them both Connect() IMO.
>
> BVI>     // Note when connecting to a base member using a deived object
> BVI>     // you must cast to the object pointer to a base as well:
> BVI>     Derived d("d");
> ...
> BVI>     handler.ConnectMember<EVT_MOTION>(&Object::fn1, static_cast<Object*>(&d));
>
>  I believe boost::signal manages to do without the case, doesn't it? So it
> should be possible to avoid it, casting like this is totally impractical.
>
>  Besides, of course, if this is completely incompatible with the existing
> code anyhow one could legitimately wonder why shouldn't we simply use
> boost::signal instead of reinventing it.
>   
I agree, I didn't know if it would be desired to use another external 
dependency or not  Possible problems:

Boost::signal is not thread safe.  Probably not much of a problem since 
all event processing and connecting/disconnecting should occur in the 
main thread anyway.
This would probably require all objects connected to derive from 
boost::signals::trackable


Brian Vanderburg II


More information about the wx-dev mailing list