Impossible event class? how to change return type w/ string?

Get answers to all your basic programming questions. No Ogre questions, please!
Post Reply
User avatar
toglia
Gnome
Posts: 336
Joined: Sat Dec 08, 2007 4:28 am
Location: Canada
x 7

Impossible event class? how to change return type w/ string?

Post by toglia »

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:

Code: Select all

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:

Code: Select all

Event event("explosion");
event.setProperty("position", Vector3()); //The second parameter could be a Variant
event.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? Seems imposible for now...
User avatar
xavier
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 9481
Joined: Fri Feb 18, 2005 2:03 am
Location: Dublin, CA, US
x 22

Re: Impossible event class? how to change return type w/ str

Post by xavier »

You can't. C and C++ do not distinguish function type based on return value type.

What you *can* do is implement getProperty as a templated member function; clearly the caller has to know the correct type to use since they are providing typed storage for it.
Do you need help? What have you tried?

Image

Angels can fly because they take themselves lightly.
User avatar
xavier
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 9481
Joined: Fri Feb 18, 2005 2:03 am
Location: Dublin, CA, US
x 22

Re: Impossible event class? how to change return type w/ str

Post by xavier »

An example probably helps here too.

Code: Select all

// MyClass.h

class MyClass
{
public:
	template <typename T>
	T myMethod(int param);
};

Code: Select all

// MyClass.cpp
 
#include "MyClass.h"

template<>
int MyClass::myMethod<int>(int param)
{
	return param;
}

template<>
double MyClass::myMethod<double>(int param)
{
	return double(param);
}

Code: Select all

// 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;
}
Do you need help? What have you tried?

Image

Angels can fly because they take themselves lightly.
User avatar
toglia
Gnome
Posts: 336
Joined: Sat Dec 08, 2007 4:28 am
Location: Canada
x 7

Re: Impossible event class? how to change return type w/ str

Post by toglia »

Cool! Got it. Thanks for the example too. Clear as water.
Bingo
Gremlin
Posts: 155
Joined: Sat Dec 10, 2005 5:30 pm

Re: Impossible event class? how to change return type w/ str

Post by Bingo »

I also use fastdelegates for delegates in my project. I encapsulated it as follows:

Code: Select all

	// class EventArgs
	class EventArgs
	{
	protected:

	public:
		EventArgs(){};
		virtual ~EventArgs(){};
	};	// eo class EventArgs

	typedef fastdelegate::FastDelegate1<EventArgs&> JooseEventDelegate;

	// class Event
	class Event
	{
	private:
		typedef std::list<JooseEventDelegate> DelegateList;
		typedef DelegateList::iterator DelegateList_it;
		DelegateList m_Delegates;
		bool		 m_bEnabled;

	public:
		Event(bool _enabled = true) : m_bEnabled(_enabled)
		{
		};	// eo ctor
		~Event()
		{
		};	// eo dtor

		// methods
		void raise(EventArgs& args)
		{
			if(!m_bEnabled)
				return;
			for(DelegateList_it dit(m_Delegates.begin());
				dit != m_Delegates.end();
				++dit)
				(*dit)(args);
		};

		// properties
		void enableEvents(bool _enabled) {m_bEnabled = _enabled;};

		// operators
		Event& operator += (JooseEventDelegate e)
		{
			m_Delegates.push_back(e);
			return(*this);
		};

		Event& operator -= (JooseEventDelegate e)
		{
			m_Delegates.remove(e);
			return(*this);
		};
	};	// eo class Event
Any object that raises events can define an event thusly:

Code: Select all

class MyObject
{
public:
    MyObject();
    ~MyObject();

    Event OnInitialise;
    Event OnDestroy;
}; // eo class MyObject
.. and can also provide any custom parameters by simply deriving from the EventArgs class:

Code: Select all

class MyEventArgs : public EventArgs
{
private:
    String someData;
    String moreData;
public:
    // etc...
};
raising an event is as simple as:

Code: Select all

MyObjectEventArgs myArgs;
OnDestroy.raise(myArgs);
Other objects interested in responding to events, do so thusly:

Code: Select all

MyObject obj;
obj.OnDestroy += fastdelegate::MakeDelegate(this, &SomeObject::HandleOnDestroy);

I find this to be quite a neat approach to using fastdelegate in a generic way.
A ship, atop a mountain, is not in itself, proof of a flood. It means someone thought there was going to be a flood.
User avatar
toglia
Gnome
Posts: 336
Joined: Sat Dec 08, 2007 4:28 am
Location: Canada
x 7

Re: Impossible event class? how to change return type w/ str

Post by toglia »

Hey Bingo, nice approach, I didn't go with the template solution either. I found it problematic cause I had know all the possible types, which "could" be possible but not very scalable. So I did something very similar using a polymorphic event class.
Post Reply