Using generic std::function objects with member functions in one class

前端 未结 6 2188
遥遥无期
遥遥无期 2020-11-22 09:41

For one class I want to store some function pointers to member functions of the same class in one map storing std::function objects. But I fail rig

6条回答
  •  执念已碎
    2020-11-22 10:29

    You can use functors if you want a less generic and more precise control under the hood. Example with my win32 api to forward api message from a class to another class.

    IListener.h

    #include 
    class IListener { 
        public:
        virtual ~IListener() {}
        virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
    };
    

    Listener.h

    #include "IListener.h"
    template  class Listener : public IListener {
        public:
        typedef LRESULT (D::*WMFuncPtr)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 
    
        private:
        D* _instance;
        WMFuncPtr _wmFuncPtr; 
    
        public:
        virtual ~Listener() {}
        virtual LRESULT operator()(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override {
            return (_instance->*_wmFuncPtr)(hWnd, uMsg, wParam, lParam);
        }
    
        Listener(D* instance, WMFuncPtr wmFuncPtr) {
            _instance = instance;
            _wmFuncPtr = wmFuncPtr;
        }
    };
    

    Dispatcher.h

    #include 
    #include "Listener.h"
    
    class Dispatcher {
        private:
            //Storage map for message/pointers
            std::map _listeners; 
    
        public:
            virtual ~Dispatcher() { //clear the map }
    
            //Return a previously registered callable funtion pointer for uMsg.
            IListener* get(UINT uMsg) {
                typename std::map::iterator itEvt;
                if((itEvt = _listeners.find(uMsg)) == _listeners.end()) {
                    return NULL;
                }
                return itEvt->second;
            }
    
            //Set a member function to receive message. 
            //Example Button->add(WM_COMMAND, this, &MyClass::myfunc);
            template  void add(UINT uMsg, D* instance, typename Listener::WMFuncPtr wmFuncPtr) {
                _listeners[uMsg] = new Listener(instance, wmFuncPtr);
            }
    
    };
    

    Usage principles

    class Button {
        public:
        Dispatcher _dispatcher;
        //button window forward all received message to a listener
        LRESULT onMessage(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
            //to return a precise message like WM_CREATE, you have just
            //search it in the map.
            return _dispatcher[uMsg](hWnd, uMsg, w, l);
        }
    };
    
    class Myclass {
        Button _button;
        //the listener for Button messages
        LRESULT button_listener(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
            return 0;
        }
    
        //Register the listener for Button messages
        void initialize() {
            //now all message received from button are forwarded to button_listener function 
           _button._dispatcher.add(WM_CREATE, this, &Myclass::button_listener);
        }
    };
    

    Good luck and thank to all for sharing knowledge.

提交回复
热议问题