Looks to me like the problem is due to casting the callback:
events[event::keypressed] += (event_handler)keypressed_event_handler;
The fact that you had to cast here is a sign that you're doing something wrong. You shouldn't just cast around compiler errors.
You have two functions here that have 2 different signatures.
Your callback takes a
int foo(const event_args& args);
Vs what you're giving it:
int foo(const keypressed_event_args& args)
And while keypressed_event_args is derived from event_args, this does not mean that you can treat them as the same type or as the same function signature.
You need to cast the pointer/reference.... not
That said, this can still be accomplished without the use of a union by doing some template trickery to handle the cast + adding the functionality to pass some userdata to the callback (ie: make it a std::function rather than using a raw function pointer).
The idea is to have a template callback within your queue class which does the parameter cast. Something like:
template<typename T> // where 'T' is a type derived from event_args
int callback( int (*userfunc)( const T& args ), const event_args& args )
return userfunc( dynamic_cast<const T&>( args ) ); // or static_cast if you trust it
You'd then add this to your callbacks... which of course would change your event_handler signature. If you do this with std::function, you can bind this so the first parameter (and thereby the template) get omitted from the signature
typedef std::function<int(const event_args&)> event_handler;
(it might also be wise to change the above 'callback' function to also use a std::function instead of a raw pointer, but whatever).
Then you can do this:
template <typename T>
event_queue& operator+=(int (*handler)( const T& args ) )
queue.push_back( std::bind( &Queue::callback, handler, std::placeholders::_1 ) );
But it would make removal a little trickier. And has a downcast. And is additional overhead in the callbacks.
Personally I don't think this approach is any better than using a union. But if you really don't want to use a union it's certainly an alternative.
EDIT: actually I'm not even sure this would work either... since this also requires the callback to be cast. So yeah this wouldn't work after all.
Just use a union.