Hi, I am implementing Component Based Architecture in my application and have recently run into a problem. The problem could be easily solved by using std::function although as a fun project I would like to try and tackle this problem without using std::function (even if that means ending up implementing my own version of std::function).
_
Problem:
I'm at the stage where I need to allow a Component to specify a callback that will be executed upon an event.
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
_
The problem with the above type definition is that all components inherit from Component but will never be a direct Component. So the following line of code is not valid:
MoveComponent* mc = new MoveComponent(); // inherits from Component
EventDelegate ed(mc , &MoveComponent::moveToXY); // Not valid because it expects Component* not MoveComponent*, and same for EventCallback.
_
Any ideas on techniques and approaches that could achieve this? Some approaches I am thinking of... any obvious/other solutions I have missed?
typedef void* EventCallback; // lazy solution
// or
// Psuedo code (I've considered using templates here but its doesn't seem to be a solution)
class EventDelegate
{
private:
// DataType = Pointer to component type (eg MoveComponent)
// Func = Pointer to component function
// Context = Pointer to component
public:
void runCallback()
{
(Context->*(void(DataType::*Func)) ();
}
};
std::unordered_map<EVENT, EventDelegate> evtRegistry;
_
Current (simplified) implementation:
typedef void(Component::*EventCallback) ();
typedef std::pair<Component*, EventCallback> EventDelegate;
class Component {
// ...
};
class MoveComponent : public Component {
public:
MoveComponent() {
EventDelegate ed(this, &MoveComponent::moveToXY);
ComponentManager::registerEvent(ed);
}
void moveToXY() { }
};
class ComponentManager {
public:
static void registerEvent(EventDelegate ed) {
evtRegistry.push_back(ed);
}
static void runEvent(EventDelegate ed) {
for (int i=0; i<evtRegistry.size(); i++) {
Component* context = evtRegistry.at(i).first;
EventCallback ec = evtRegistry.at(i).second;
context->*ec();
}
}
private:
static std::vector <EventDelegate> evtRegistry; // vector for a simple example. Really a std::unordered_multimap<EVENT, EventDelegate>
};