   tricky template inheritance
  I am working on a event handling framework using templates.The ambition is to let it work by direct function calls withoutpassing objects. // First the class CEventListener and CEventSource:template< class TEvent >class CEventListener {public:  virtual void OnNotify() {};};template< class TEvent >class CEventSource {protected:std::vector< CEventListener< TEvent > *> m_vpListeners;void NotifyListeners() const{std::vector< CEventListener < TEvent > *>::const_iterator iter = m_vpListeners.begin();for (; iter != m_vpListeners.end(); iter++) {(*iter)->OnNotify();}}//And now an example how it would be used in a //class that sould be a listener for some eventsclass CTest : public CEventListener< int > , public CEventListener< float> {//The following will not compile but it should describe what I //want to do..void OnNotify() { std::cout << "int event \n"; }void OnNotify() { std::cout << "float event \n"; }}; In CTest the virtual functions OnNotify() form CEventListener< int > and form CEventListener< float > should be overloaded. But I don't know how to do this. I know the solutionof OnNotify(TEvent &) but I want to do this without passing objects.Is there any way to do this?Thanks,Constantin[edited by - conman on February 9, 2004 8:14:04 AM]
  Hello conman,I think all you need is this:class CTest : public CEventListener< int > , public CEventListener< float> {//The following will not compile but it should describe what I //want to do..void CEventListener < int>::OnNotify() { std::cout << "int event \n"; }void CEventListener < float>::OnNotify() { std::cout << "float event \n"; }};So the compiler know for sure what method to use.Lord Bart It took out my < > and what was in between   [edited by - lord bart on February 9, 2004 12:41:59 PM] [edited by - lord bart on February 9, 2004 12:43:12 PM];  @Lord Bart:What you wrote:void CEventListener::OnNotify() { ... }void CEventListener::OnNotify() { ... }  makes not so much sense, cause the compile would not know witch superclass is meant.void CEventListener< int > ::OnNotify() { ... }void CEventListener< float > ::OnNotify() { ... }  would have more sense, but it''s not allowed either.Thanks anyway!;  My event system is typesafe, and uses rudimentary type erasure. It works by passing the event itself to the handlers. Since we always deal with the derived type of event at compile time we can carry the type information around.Not wanting to pass objects around is highly misguided, anyway. #ifndef CORE_EVENTS_EVENTBASE_HPP#define CORE_EVENTS_EVENTBASE_HPP#include <memory>#include "../Export.hpp"#include "EventSystem.hpp"#include "Handler.hpp"namespace OpenIM{namespace Events{template<class DerivedEventT>class Event{public:template<typename ClassT>class Handler :public OpenIM::Events::Handler{public:typedef void (ClassT::* MemberFn)(DerivedEventT&);Handler(ClassT* inst, MemberFn fn) :instance(inst),function(fn){}void operator()(void* arg){(instance->*function)(*static_cast<DerivedEventT*>(arg));}bool operator==(OpenIM::Events::Handler* rhs){if(Event<DerivedEventT>::Handler<ClassT>* h = dynamic_cast<Event<DerivedEventT>::Handler<ClassT>*>(rhs))return this->instance == h->instance && this->function == h->function;elsereturn false;}private:ClassT* instance;MemberFn function;};template<class ClassT>static void Attach(ClassT* instance, void(ClassT::* fn)(DerivedEventT&)){std::auto_ptr<Event<DerivedEventT>::Handler<ClassT> > handler(new Event<DerivedEventT>::Handler<ClassT>(instance, fn));EventSystem::Attach(DerivedEventT::Name(), handler.get());handler.release();}template<class ClassT>static void Detach(ClassT* instance, void(ClassT::* fn)(DerivedEventT&)){std::auto_ptr<Event<DerivedEventT>::Handler<ClassT> > handler(new Event<DerivedEventT>::Handler<ClassT>(instance, fn));EventSystem::Detach(DerivedEventT::Name(), handler.get());}void Trigger(){EventSystem::Trigger(DerivedEventT::Name(), static_cast<void*>(static_cast<DerivedEventT*>(this)));}};}}#endifI'm working on a RTTI-less version of this right now. Obviously this is not the whole thing, let me know if you want the source to the EventSystem (this is a GPL project).BTW I cast to void* to allow less-typesafe languages (C) to respond to events.   [edited by - antareus on February 9, 2004 12:25:52 PM];  If this isn''t meant for leaning, I''d suggest you to use either libSigC++ or Boost::Signal. Both provide the functionality you want, typesafe multicast callbacks to class methods, but also plain functions and functors.-Markus-;  @cygon:I''ll take a look at this, but actually I wanted to implement it myself.. @antareus:Thanks for your post! Your event system seems very complex, but I don''t understand why not passing objects is misguided? It''s for example not necessary to pass an object for an simple repaint event. I tryed to look at the generated asm code if a simple CRepaintEvent would be optimised away if it''s only function is to choose the right function in the subclass,but I am not sure at this point...-Constantin ;  I''m not a fan of deriving from "listener"-type classes. C++ has support for event handlers through either Loki/Boost or hand-rolled (I needed operator== for functors BTW).quote:Your event system seems very complexThat is the 9th or so iteration of it, I still need to add back in handler ordering. It works very well for me and is a hybrid functor/signals and slots approach.quote:I don''t understand why not passing objects is misguided? It''s for example not necessary to pass an object for an simple repaint event.For a repaint event you might not need any information. However, I''m sure other events would need some information, and putting them all into a single struct makes it easy: /// A contact has been added to a specific group. The group may be null, indicating it is not a member of any group.struct ContactAddEvent :public Event<ContactAddEvent>{static OpenIM::StringName() { return L"ContactAddEvent"; }OpenIM::Contact*contact;OpenIM::Group*group;};The event handler I showed I use for application level events, as you can see from the example. 