3

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 ?

wohlstad
36.6k18 gold badges79 silver badges113 bronze badges
asked Mar 2, 2025 at 12:42
3
  • 2
    Try (e.first->*(e.second))(m) Commented Mar 2, 2025 at 12:45
  • 1
    One thing is that your typedef should be moved below class event_receiver { ... }; because it refers to event_receiver::.... Commented Mar 2, 2025 at 12:50
  • 2
    for (auto&& [receiver, callback] : suscribers_vec) would make the code read better. Then invoked by (receiver->*callback)(m);. Commented Mar 2, 2025 at 13:50

1 Answer 1

6

There are several issues in your code:

  1. Your typedef for ev_rec_func has to be declared after class event_receiver { ... }; because it refers to event_receiver::... and so event_receiver must already be known.

    Note: you can consider to replace the typedef with a more modern type alias (AKA using declaration):

    using ev_rec_func = void(event_receiver::*)(const event_receiver::Msg&);
    
  2. 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.

Live demo

answered Mar 2, 2025 at 13:02
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.