I'm trying to create sort of an event system, I don't care if it is suboptimal, I'm doing it for fun. I do not want alternate solutions, I want to understand why this isn't working and how could I fix it.
I'm using this page as reference to do so "https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types"
I want event_triggerer to store the functions it needs to call from event_receiver and be able to call them on the stored object
This is the relevant code:
typedef void(event_receiver::* ev_rec_func)(const event_receiver::Msg&);
class event_receiver {
public:
struct Msg {
int irrelevant_test_data;
};
virtual void event_callback0(const Msg& m) {};
};
class event_triggerer {
private:
std::vector<std::pair<event_receiver*, ev_rec_func>> suscribers_vec;
public:
void trigger_event(const event_receiver::Msg& m) {
for (std::pair<event_receiver*, ev_rec_func>& e : suscribers_vec) {
//this line show the error expression must have pointer to member type
e.first->*(e.second(m));
}
}
Visual Studio displays this when I hover over ev_rec_func:
typedef void ev_rec_func(const &)
But I cannot understand why.
Im not really used to typedef syntax, so I guess there's something wrong with it.
I also found this answer but could not understand whats wrong with mine C++: Calling member function via pointer
I rewrote this line e.first->*(e.second(m)); as "(e.first->*e.second)(m); but it still generates an error, this time is:
"a pointer to a bound function may only be used to call the function"
How can I solve the error ?
1 Answer 1
There are several issues in your code:
Your
typedefforev_rec_funchas to be declared afterclass event_receiver { ... };because it refers toevent_receiver::...and soevent_receivermust already be known.Note: you can consider to replace the
typedefwith a more modern type alias (AKA using declaration):using ev_rec_func = void(event_receiver::*)(const event_receiver::Msg&);As @DominikKaszewski commented, you have to change the method invoke syntax to:
(e.first->*(e.second))(m);The reason is that it is a matter of Operator Precedence.
Comments
Explore related questions
See similar questions with these tags.
(e.first->*(e.second))(m)typedefshould be moved belowclass event_receiver { ... };because it refers toevent_receiver::....for (auto&& [receiver, callback] : suscribers_vec)would make the code read better. Then invoked by(receiver->*callback)(m);.