I'm trying to implement subscriber-publisher pattern. My base class Subscriber doesn't have a listener method, it declares type Handler instead. The idea behind this is that a derived class will be able to have multiple handlers which will implement this type and can be passed to a Publisher. I'm trying to invoke a handler in Notify method, but I'm getting an error which states expression must have pointer-to-member type. How can I cast my function pointer to a member type and is it even possible with my approach?
class Subscriber {
public:
typedef void (*Handler)();
};
struct Subscription {
Subscriber *instance;
Subscriber::Handler handler;
};
class Publisher {
protected:
std::vector<Subscription> subscriptions;
public:
virtual void AddSubscriber(Subscription subscription) {
this->subscriptions.push_back(subscription);
};
virtual void Notify() {
for (auto subscription : this->subscriptions) {
auto i = subscription.instance;
auto h = subscription.handler;
(i->*h)();
}
};
};
My goal is to make an expandable system to be able to do something like this
struct KeyboardSubscription : Subscription {
Event event_type;
Key listened_key;
}
class GUI : Subscriber {
void OpenMenu() { ... }; // implementing Subscriber::Handler
void CloseMenu() { ... }; // implementing Subscriber::Handler too
}
class Keyboard : Publisher {
void Notify() {
for (KeyboardSubscription subscription : this->subscriptions) {
auto i = subscription.instance;
auto h = subscription.handler;
if (subscription.event_type == this->event_type &&
subscription.listened_key == this->pressed_key)
(i->*h)();
}
}
}
int main() {
// init GUI and Keyboard...
KeyboardSubscription sub1;
sub1.instance = gui_instance;
sub1.handler = &GUI::OpenMenu;
sub1.event_type = Key_Down;
sub1.listened_key = Enter;
KeyboardSubscription sub2;
sub2.instance = gui_instance;
sub2.handler = &GUI::CloseMenu;
sub2.event_type = Key_Down;
sub2.listened_key = Esc;
keyboard_instance.AddSubscription((Subscription)sub1);
keyboard_instance.AddSubscription((Subscription)sub2);
}
(i->*h)();->h()... no need fori. Or justsubscription->handler();In yourauto h = subscription->handler;, the deduced type forhisSubscriber::Handler, so no need for a cast. Or have I totally missed the point, here?typedef void (*Handler)(Subscriber*);and then call in yourNotifylikeh(i);. Maybe we need more details here, like a sample of usage code?handleras a member function; it is a data member whose type is a function pointer (to a free function).