How to store class function to vector of pointers?

For now, I made this:

1
2
3
4
5
6
7
	void f(sf::Event* event) {

		std::cout << event->mouseMove.x << std::endl;

	}

        engine.registerListener(sf::Event::EventType::KeyPressed, f);


--------------------------------------------------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	typedef void(*listenerFunction)(sf::Event*);

	class EventManager {

		friend class Engine;

	private:

		std::map<sf::Event::EventType, std::vector<listenerFunction>> listeners;

		void triggerEvent(sf::Event* event);

	public:

		void registerListener(sf::Event::EventType event_type, listenerFunction listener);

	};


And it worked fine. Then I tried with class function and there was an problem. So I searched the internet for a solution and I found I need to make static functin. It worked. My question is how can I store different class function pointers without making function static?
Last edited on
Use the polymorphic call wrapper std::function<> to wrap the call, and std::bind() to bind the this pointer.

Something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <map>
#include <functional>
#include <vector>

namespace sf {

    struct Event {

        enum class EventType { KeyPressed /* ... */ } ;

        EventType type ;

        // ...
    };
}

struct EventManager {

    // http://en.cppreference.com/w/cpp/utility/functional/function
    // listener function is wrapped in a polymorphic call wrapper
    using listenerFunction = std::function< void(sf::Event) > ;

    // resister generic callable object
    void registerListener( sf::Event::EventType event_type, listenerFunction listener ) {

        listeners[event_type].push_back( std::move(listener) ) ;
    }

    template < typename CLASS, typename MEMFN > // register member function of class 'CLASS'
    void registerListener( sf::Event::EventType event_type, CLASS* object, MEMFN memfn ) {

        // http://en.cppreference.com/w/cpp/utility/functional/bind
        // generate a forwarding call wrapper after binding the first argument
        // (which becomes the this pointer)
        listeners[event_type].push_back( std::bind( memfn, object, std::placeholders::_1 ) ) ;
    }

    void triggerEvent( sf::Event event ) {

        const auto iter = listeners.find( event.type ) ;
        if( iter != listeners.end() ) for( const auto& fn : iter->second ) fn(event) ;
    }

    private: std::map< sf::Event::EventType, std::vector<listenerFunction> > listeners;

};


int main() {

    struct A {

        void member_handle_event( sf::Event ) {

            std::cout << "handle event in member function of main::A\n" ;
        }
    };
    A object_a;

    const auto non_member_handle_event = [] ( sf::Event ) {

            std::cout << "handle event in non-member function\n" ;
    };

    EventManager mgr ;

    // register member function of A
    mgr.registerListener( sf::Event::EventType::KeyPressed, std::addressof(object_a), &A::member_handle_event ) ;

    // register non-member function
    mgr.registerListener( sf::Event::EventType::KeyPressed, non_member_handle_event ) ;

    mgr.triggerEvent( { sf::Event::EventType::KeyPressed } ) ;
}

http://coliru.stacked-crooked.com/a/9a13ef62c1d2797b
http://rextester.com/RAGJM22198
You might consider making class EventManager a friend of the class (Engine?) that has the functions it needs to point to
It's not working :/
http://i.imgur.com/9tvzFf4.png
Example by JBorges worked for me. Make sure that you have C++11 enabled. If you use gcc or clang++, add -std=c++11 option to command line.
Without C++11 you can use function pointers to call class member function:
for class
1
2
3
4
class A {
public:
    int member_function(int arg);
};

pointer to A::member_function can be declared and called:
1
2
3
4
5
6
int main()
{
    int (A::*pointer)(int arg) = &A::member_function; 
    A a;
    (a.*pointer)(1);
}

alternatively with typedef:
1
2
3
4
5
6
7
typedef int (A::*fpointer)(int arg);
int main()
{
    A a;
    fpointer pointer = &A::member_func;
    (a.*pointer)(1);
}
Last edited on
Topic archived. No new replies allowed.