   Using map to decide return type, impossible design?
  Hi, I'm doing my first event system in C++ using fastdelegates(codeproject) and although its already working, I'm thinking of doing a cleaner design.Well, the basic problem when using delegates is that it is necessary to specify the handler's parameter types. So first I started using a Variant class based on a union, but later switched to simple pointers cause I couldn't use custom constructors.I ended up with something like:eventManager->defineEvent("explosion"); Person *person = new Person();eventManager->bindEvent("explosion", EventManager::Delegate2(person, &Person::OnExplosion));eventManager->fireEvent("explosion", Variant(Vector3(1,2,3)), Variant(0.5f));void Person::OnExplosion(Variant* v1, Variant* v2){v1->getVector3Ptr();//...Not bad, but I hate the getVector3Ptr stuff cause people who use this event has to know the order AND the type of the Event.Then I started thinking maybe I could use a map to pair names with types, but I can't figure out a way to do it.I would like to have:Event event("explosion");event.setProperty("position", Vector3()); //The second parameter would be a Variantevent.setProperty("force", int(10));eventManager->fireEvent("explosion", event);void Person::OnExplosion(Event* e){Vector3 v = e->getProperty("position"); //How to do this?float f = e->getProperty("force"); //Same function returns a Vector3 and a float?//...This would be very elegant, but how in the world can I change the return type of a function if I pass the same parameter type?[Edited by - toglia on May 19, 2010 9:25:36 PM]
  Probably the best way would be to template the method. This thread will probably tell you all you need.   ;struct ExplosionEventData : public EventData {   Vector3 Position;   float Force;};eventManager->fireEvent("explosion", new ExplosionEventData{Vector3(1.0f,2.0f,3.0f), 100.0f});void Person::OnExplosion(const EventData* data) {   const ExplosionEventData* explosionData = static_cast<const ExplosionEventData*>(data);   dealDamage(distanceTo(explosionData->Position), explosionData->Force);   // ...}This is typically how you'd pass around custom data in an event system.  An attribute system would also work, but it's a lot of overkill if you don't need the functionality.   ;  I don't know why I rejected that possibility in the first place, I sure thought about it. weird!Anyway, this is how the template function works.// MyClass.hclass MyClass{public:   template <typename T>   T myMethod(int param);};// MyClass.cpp#include "MyClass.h"template<>int MyClass::myMethod<int>(int param){   return param;}template<>double MyClass::myMethod<double>(int param){   return double(param);}// main.cpp#include "MyClass.h"int main(int argc, char* argv[]){   MyClass dInst;   // this is fine because we implemented this specifically   double x = dInst.myMethod<double>(4);   // this is fine because we implemented this specifically   int y = dInst.myMethod<int>(9);   // this will link-error because it's not defined anywhere   float f = dInst.myMethod<float>(100);   return 0;}Xavier from Ogre's forum helped me out.I'm still undeceive. I like that I would have to code less using the template way, I would not be casting which is also good.What do you think?   ;  You don't need template specializations.boost::variant<> is basically your original union-based variant, only without unions, with type safety, and with extremely high speed.  #include <boost/variant.hpp>#include <map>class foo{   typedef boost::variant<int, double, std::string, class bar> prop_type;   typedef std::map<std::string, prop_type> property_map;   property_map properties;public:   template<typename T>   T getProperty(const std::string& name) const   { const prop_type& prop = properties[name]; return boost::get<T>(prop);   }};float dist = foo.getProperty<float>("accelerationProp");string name = foo.getProperty<string>("nameProp");bar b = foo.getProperty<bar>("barProp");;  What would you say is faster or has better memory alignment the casting or this variant/union method? I really like both. Not sure what to choose for this EventManager now...The only *bad* thing I see, is that with variants I need to know all possible event arguments, which isn't that big deal either.[Edited by - toglia on May 20, 2010 3:38:36 AM];Quote:Original post by togliaThe only *bad* thing I see, is that with variants I need to know all possible event arguments, which isn't that big deal either.I probably shouldn't have said earlier that an attribute approach would also work, because in retrospect it only works well in cases where you know for sure there are only ever going to be X different types, and that all event data can be expressed as a combination of those types.  Otherwise you're pigeonholing client code for no reason.  Every time you want to pass a new type into an event you need to touch the low-level event system code (which might not even be an option), and on top of that any types you add must be available at the event system level.  On top of that, you then need to go through and extract each individual parameter using a special name or key object or whatever, which might involve a map look-up or something similar.  Just getting the data into and out of the attribute container in itself is an entire process, the latter of which is repeated for every delegate that handles the event.  And what happens if an attribute doesn't exist?IMHO a polymorphic event type is going to be the easiest to implement, and the easiest for higher-level code to use and expand upon.  Plus you can avoid or mitigate a lot of the aforementioned issues.   