Reputation: 437
I'm constructing an simple listener / callback mechanism, for my current experimental project. And i'm stuck with implementing a container structure what seems should be vector of vector of pointers. I choose this way because i want the root vector to simple have KEY of event type let's say is an enum (int), then at this key i want to store vector of pointers to available methods for this event type. In logical representation something like:
[EVENT_TYPE_QUIT]
[ptr1]
[ptr2]
[ptr3]
[ptr4]
[....]
[EVENT_TYPE_HELLO]
[....]
[....]
typedef enum {
EVENT_TYPE_QUIT,
EVENT_TYPE_HELLO,
...
} EventType;
So the simplified implementation looks something like this (it's an template in reality but imagine T is any user type you can map an event).
class EventMapper {
...
typedef void (T::*functionPtr)(); // simple pointer to T member function with no args.
std::vector< std::vector<functionPtr> > eventCallbacks;
void mapEvent(const EventType type, functionPtr callback) {
// here i need to map type to callback
// each type can have multiple callbacks
// T can have only distinct event types as "key"
// this i tried but doesn't work
eventCallbacks[type].push_back(callback);
}
...
}
The intended implementation would look something like:
EventMapper<SupaDupaClass> mapper;
mapper.mapEvent(EVENT_TYPE_HELLO, &SupaDupaClass::didYouSayHello);
etc ...
I really would like to use vector instead of map for easier unique key assignment ? Thank you
Upvotes: 0
Views: 528
Reputation: 3112
You can use a std::map
to map the event_type to the vector of callbacks. And consider using std::function
instead of function pointers for flexibility.
One possible implementation is:
#include <vector>
#include <map>
#include <functional>
#include <iostream>
enum class event_type
{
event_one,
event_two
};
void func1() { std::cout << "func1" << std::endl; }
class my_listener { public: void func() { std::cout << "my_listener::func" << std::endl; } };
int main()
{
std::map<event_type, std::vector<std::function<void ()>>> m;
my_listener lst;
m[event_type::event_one].push_back(std::bind(&my_listener::func, lst));
m[event_type::event_one].push_back(&func1);
// invoke callbacks (may be used in the code that raises events)
for(auto& kv : m)
{
for(auto& f : kv.second) {
f();
}
}
return 0;
}
EDIT: You might consider using Boost.Signals2 library.
Upvotes: 1
Reputation: 6921
If I read you code correctly, you are accessing an uninitialized entry.
You should first initialize the eventCallbacks with empty vectors, something like
eventCallbacks.assign(10,std::vector())
Upvotes: 1