C ++ 11 рдФрд░ рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд┐рдВрдЧ

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдУрдУрдкреА рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рдХреЗ рддрд░реАрдХреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдИрд╡реЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд▓рдЧрднрдЧ рд╕рднреА рдХреЛ рдЬреНрдЮрд╛рдд рд╣реИ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдХрднреА рднреА рдУрдУрдкреА рдХреЛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмрд╛рд░ рдЫреБрдЖ рд╣реИред рдХрдо рд╕реЗ рдХрдо, рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрд╣реБрдд рд╡реНрдпрд╛рдкрдХ рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╢реНрд░реЗрдгреА рдореЗрдВ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдХрдИ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ, рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдЗрдВрдЬрди рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╣реИ; рд╣рд╛рд▓рд╛рдБрдХрд┐, C ++ рдореЗрдВ рдРрд╕рд╛ рдХреЛрдИ рддрдВрддреНрд░ рдирд╣реАрдВ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЖрдк рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкрд░рд┐рдЪрдп


рдПрдХ рдШрдЯрдирд╛ рдПрдХ рдРрд╕реА рдЪреАрдЬ рд╣реИ рдЬреЛ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЗ рддрд╣рдд рд╣реЛ рд╕рдХрддреА рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдмрдЯрди рдХреЗ рд╕рд╛рде рдЬрдм рдЖрдк рдЙрд╕ рдкрд░ рдорд╛рдЙрд╕ рд╕реЗ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ)ред рдЕрдиреНрдп рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЗрд╕рд╕реЗ рдЕрд╡рдЧрдд рд╣реЛрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ; рддрдм рд╡реЗ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВ ред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЬрдм рдХреЛрдИ рдШрдЯрдирд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдХрд┐рд╕реА рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╕рджрд╕реНрдпрддрд╛ рджреА рдЬрд╛рддреА рд╣реИ рдЬрд┐рд╕реЗ рдШрдЯрдирд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ; рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЙрд╕рдХреЗ рдкрд╛рд╕ рдХреБрдЫ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рд╣реИ, рдЕрд░реНрдерд╛рддред рдПрдХ рдШрдЯрдирд╛ рдХрд╛ рдЬрд╡рд╛рдмред рдЗрд╕реА рддрд░рд╣, рдПрдХ рд╡рд╕реНрддреБ рдХрд┐рд╕реА рдШрдЯрдирд╛ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рд╕рдХрддреА рд╣реИ рдпрджрд┐ рд╡рд╣ рдЕрдм рдЙрд╕ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рджреЗрдирд╛ рдЪрд╛рд╣рддреА рд╣реИред рдирддреАрдЬрддрди, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рд╡рд╕реНрддреБрдПрдВ рд╣реИрдВ рдЬреЛ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреА рдШрдЯрдирд╛рдУрдВ рдФрд░ рджреВрд╕рд░реЛрдВ рдХреА рдЗрди рдШрдЯрдирд╛рдУрдВ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ-рджреВрд╕рд░реЗ рд╕реЗ рдЬреБрдбрд╝реА рд╣реЛ рд╕рдХрддреА рд╣реИрдВред

рдРрд╕рд╛ рдХреБрдЫ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╣рд░ рдХреЛрдИ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ред

рд╕рдмрд╕реЗ рд╕рд░рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдЗрд╕ рддрд░рд╣ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╕рд╛рди рдкреНрд░рддреАрдд рд╣реЛрдЧрд╛ред рдФрд░ рдпрд╣ рдЗрд╕ рддрд░рд╣ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ:

template<class ...TParams> class AbstractEventHandler { public: virtual void call( TParams... params ) = 0; protected: AbstractEventHandler() {} }; 

 template<class ...TParams> class TEvent { using TEventHandler = AbstractEventHandler<TParams...>; public: TEvent() : m_handlers() { } ~TEvent() { for( TEventHandler* oneHandler : m_handlers ) delete oneHandler; m_handlers.clear(); } void operator()( TParams... params ) { for( TEventHandler* oneHandler : m_handlers ) oneHandler->call( params... ); } void operator+=( TEventHandler& eventHandler ) { m_handlers.push_back( &eventHandler ); } private: std::list<TEventHandler*> m_handlers; }; 

 template<class TObject, class ...TParams> class MethodEventHandler : public AbstractEventHandler<TParams...> { using TMethod = void( TObject::* )( TParams... ); public: MethodEventHandler( TObject& object, TMethod method ) : AbstractEventHandler<TParams...>(), m_object( object ), m_method( method ) { assert( m_method != nullptr ); } virtual void call( TParams... params ) override final { ( m_object.*m_method )( params... ); } private: TObject& m_object; TMethod m_method; }; template<class TObject, class ...TParams> AbstractEventHandler<TParams...>& createMethodEventHandler( TObject& object, void( TObject::*method )( TParams... ) ) { return *new MethodEventHandler<TObject, TParams...>( object, method ); } #define METHOD_HANDLER( Object, Method ) createMethodEventHandler( Object, &Method ) #define MY_METHOD_HANDLER( Method ) METHOD_HANDLER( *this, Method ) 

рдЗрд╕ рдорд╛рдорд▓реЗ рдХрд╛ рдЖрд╡реЗрджрди рдлреЙрд░реНрдо рдХрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:

 class TestWindow { . . . public: TEvent<const std::string&, unsigned int> onButtonClick; . . . }; class ClickEventHandler { . . . public: void testWindowButtonClick( const std::string&, unsigned int ) { ... } . . . }; int main( int argc, char *argv[] ) { . . . TestWindow testWindow; ClickEventHandler clickEventHandler; testWindow.onButtonClick += METHOD_HANDLER( clickEventHandler, ClickEventHandler::testWindowButtonClick ); . . . } 

рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рдПрдХ рд╣реИрдВрдбрд▓рд░-рд╡рд┐рдзрд┐ (рдПрдХ рд╡рд░реНрдЧ рдХрд╛-рд╕рджрд╕реНрдп-рд╕рджрд╕реНрдп) рдХреЗрд╡рд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВрдбрд▓рд░ рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдмрд╛рдж рдореЗрдВ рдЙрд╕ рдкрд░ рдЕрдзрд┐рдХред

рд╕рдм рдХреБрдЫ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ, рдХреЙрдореНрдкреИрдХреНрдЯ рдФрд░ рд╢рд╛рдирджрд╛рд░ рд▓рдЧрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЬрдмрдХрд┐ рдХрдИ рдХрдорд┐рдпрд╛рдВ рд╣реИрдВред

рд╣реИрдВрдбрд▓рд░ рддреБрд▓рдирд╛


рдХрд┐рд╕реА рдИрд╡реЗрдВрдЯ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╣реИрдВрдбрд▓рд░ ( = = ! == ) рд╕реЗ рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕реЗ рд╣реИрдВрдбрд▓рд░ рдЬреЛ рдПрдХ рд╣реА рд╡рд╕реНрддреБ (рдПрдХ рд╣реА рд╡рд░реНрдЧ рдХреЗ рдПрдХ рд╕рджрд╕реНрдп) (рдпрд╛рдиреА рдПрдХ рд╣реА рд╡рд░реНрдЧ рдХреЗ рдПрдХ рд╣реА рдЙрджрд╛рд╣рд░рдг) рдХреЗ рдПрдХ рд╣реА рд╡рд┐рдзрд┐ (рдпрд╛рдиреА рдПрдХ рд╕рджрд╕реНрдп рдлрд╝рдВрдХреНрд╢рди) рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдХреЛ рд╕рдорд╛рди рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ред

 template<class ...TParams> class AbstractEventHandler { . . . using MyType = AbstractEventHandler<TParams...>; public: bool operator==( const MyType& other ) const { return isEquals( other ); } bool operator!=( const MyType& other ) const { return !( *this == other ); } protected: virtual bool isEquals( const MyType& other ) const = 0; . . . }; 

 template<class TMethodHolder, class ...TParams> class MethodEventHandler : public AbstractEventHandler<TParams...> { . . . using TMethod = void( TObject::* )( TParams... ); protected: virtual bool isEquals( const AbstractEventHandler<TParams...>& other ) const override { const MyType* _other = dynamic_cast<const MyType*>( &other ); return ( _other != nullptr && &m_object == &_other.m_object && m_method == _other.m_method ); } private: TObject& m_object; TMethod m_method; . . . }; 

рддрдм рд╣рдо рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЗрд╡реЗрдВрдЯ рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рд╕реЗ рд╣рдЯрд╛ рдкрд╛рдПрдВрдЧреЗред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдорд╛рди (рд╕рдорд╛рди) рд╣реИрдВрдбрд▓рд░реНрд╕ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдкрд░ рд░реЛрдХ рд▓рдЧрд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

 template<class ...TParams> class TEvent { . . . using TEventHandler = AbstractEventHandler<TParams...>; using TEventHandlerIt = typename std::list<TEventHandler*>::const_iterator; public: bool operator+=( TEventHandler& eventHandler ) { if( findEventHandler( eventHandler ) == m_handlers.end() ) { m_handlers.push_back( &eventHandler ); return true; } return false; } bool operator-=( TEventHandler& eventHandler ) { auto it = findEventHandler( eventHandler ); if( it != m_handlers.end() ) { TEventHandler* removedEventHandler = *it; m_handlers.erase( it ); delete removedEventHandler; return true; } return false; } private: inline TEventHandlerIt findEventHandler( TEventHandler& eventHandler ) const { return std::find_if( m_handlers.cbegin(), m_handlers.cend(), [ &eventHandler ]( const TEventHandler* oneHandler ) { return ( *oneHandler == eventHandler ); } ); } std::list<TEventHandler*> m_handlers; . . . }; 

рдпрд╣рд╛рдБ, рд╣реИрдВрдбрд▓рд░ рдХреЗ рдРрдб / рд░рд┐рдореВрд╡ рдлрд╝рдВрдХреНрд╢рдВрд╕ рд╕рд╣реА рдФрд░ рд╕рдлрд▓ рд╣реЛрддреЗ рд╣реИрдВ, рдпрджрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдПрдХреНрд╢рди (рдРрдб рдпрд╛ рд░рд┐рдореВрд╡) рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рддреЛ рд╡рд╣ рд╕рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рд╣рд╛рдВ, рддреБрд▓рдирд╛ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрд╕реНрдерд╛рдпреА, рдХрд╣реАрдВ рднреА рдЬреЛрдбрд╝рд╛ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬреЛ рдХрд╣реАрдВ рднреА рд╣рдЯрд╛рдП рдирд╣реАрдВ рдЬрд╛рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЙрд╕ рдкрд░ рдФрд░ рдмрд╛рдж рдореЗрдВред

рдХреНрдпрд╛ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдЕрднреА рддрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реБрдЖ рд╣реИред

рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ рд╣реИрдВрдбрд▓рд░ рдирд┐рдХрд╛рд▓рдирд╛


рдЗрд╕рд▓рд┐рдП, рд╣рдо рддреБрд░рдВрдд рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рдПрдХ рджреБрд░реНрдШрдЯрдирд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╣реИрдВрдбрд▓рд░ рдЦреБрдж рдХреЛ рдШрдЯрдирд╛ рд╕реЗ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИ (рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рджреНрд╡рд╛рд░рд╛ рд╕реНрд╡рдпрдВ-рдХрдЯреМрддреА рдХрд░рдиреЗ рдкрд░ рд╕рдмрд╕реЗ рджреБрд░реНрд▓рдн рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ):

 class TestWindow { . . . public: TEvent<const std::string&, unsigned int> onButtonClick; static TestWindow& instance(); . . . }; class ClickEventHandler { . . . public: void testWindowButtonClick( const std::string&, unsigned int ) { TestWindow::instance().onButtonClick -= MY_METHOD_HANDLER( ClickEventHandler::testWindowButtonClick ); } . . . }; int main( int argc, char *argv[] ) { . . . ClickEventHandler clickEventHandler; TestWindow::instance().onButtonClick += METHOD_HANDLER( clickEventHandler, ClickEventHandler::testWindowButtonClick ); . . . } 

рд╕рдорд╕реНрдпрд╛ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд╛рдзрд╛рд░рдг рдХрд╛рд░рдг рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ:

  • рдШрдЯрдирд╛ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ (рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП) рд╣реИрдВрдбрд▓рд░, рдЙрдиреНрд╣реЗрдВ рдмреБрд▓рд╛рддреЗ рд╣реБрдП;
  • рдЕрдЧрд▓реЗ рд╣реИрдВрдбрд▓рд░ рдХреЗ рднреАрддрд░ рд╣реА рдЦреБрдж рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ;
  • рдИрд╡реЗрдВрдЯ рджрд┐рдП рдЧрдП рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реИ, рдЬреЛ рд╕рдВрдмрдВрдзрд┐рдд рдЗрдЯреЗрд░реЗрдЯрд░ рдХреЛ рдЕрдорд╛рдиреНрдп рдмрдирд╛рддрд╛ рд╣реИ;
  • рдЗрд╕ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдИрд╡реЗрдВрдЯ рджреВрд╕рд░реЛрдВ рдХреЛ рдПрдиреБрдорд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд░реНрддрдорд╛рди рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ (рд░рд┐рдореЛрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░) рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдорд╛рдиреНрдп рд╣реИ;
  • рдИрд╡реЗрдВрдЯ рдЕрдорд╛рдиреНрдп рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЧрд┐рд░рд╛рд╡рдЯ рд╣реЛ рд╕рдХрддреА рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдорд╛рдорд▓реЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрдм рд╣реИрдВрдбрд▓рд░ рдХреА рд╕реВрдЪреА рдХреЛ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЛ рдЕрдорд╛рдиреНрдп рдХрд░ рджреЗрдЧрд╛; рдФрд░ рдлрд┐рд░ рдРрд╕реЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд░реАрдб рдкреНрд░реЛрдЯреЗрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд░реЗрдВред

рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ std :: list 'рдХрд╛ рд▓рд╛рдн рдпрд╣ рддрдереНрдп рд╣реИ рдХрд┐ рдЬрдм рдЗрд╕реЗ рд╣рдЯрд╛рдиреЗ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдЕрдорд╛рдиреНрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ - рд╣рдЯрд╛рдП рдЧрдП рддрддреНрд╡ рдкрд░ (рдкреНрд░рднрд╛рд╡рд┐рдд, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрди); рдФрд░ рдПрдХ рддрддреНрд╡ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдХрд┐рд╕реА рднреА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреЛ рдЕрдорд╛рдиреНрдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдорд╛рдорд▓реЗ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдПрдХ рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛рдирд╛ рдЬрд┐рд╕рдХрд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рддрддреНрд╡реЛрдВ рдХреА рд╡рд░реНрддрдорд╛рди рдЧрдгрдирд╛ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд┐рд╕реА рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдпрд╣ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╡рд░реНрддрдорд╛рди рддрддреНрд╡ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рддрддреНрд╡реЛрдВ рдХреА рдЧрдгрдирд╛ рдХреЗ рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдХреЛрдИ рднреА рддреБрд░рдВрдд рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВред

рдзрд╛рдЧрд╛ рд╕реБрд░рдХреНрд╖рд╛


рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ, рддреАрди рд╕рдВрднрд╛рд╡рд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ - рдЬреЛрдбрд╝рдирд╛, рд╣рдЯрд╛рдирд╛, рдФрд░ рд╕реЙрд░реНрдЯ рдХрд░рдирд╛ (рдЬрдм рдХреЛрдИ рдШрдЯрдирд╛ рдЯреНрд░рд┐рдЧрд░ рд╣реЛрддреА рд╣реИ) рд╣реИрдВрдбрд▓рд░ - рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдордп рдкрд░ рд╡рд┐рднрд┐рдиреНрди рдереНрд░реЗрдбреНрд╕ рд╕реЗ рд╕рдВрднрд╡ рд╣реИрдВред рдпрд╣ рд╕рдордп рдореЗрдВ рдЙрдирдХреЗ "рдЪреМрд░рд╛рд╣реЗ" рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХрд╛ рдПрдХ рд╕рдВрдкреВрд░реНрдг рдХреНрд╖реЗрддреНрд░ рдмрдирд╛рддрд╛ рд╣реИ, рдПрдХ рджреВрд╕рд░реЗ рдкрд░ рдЙрдирдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ "рдЕрддрд┐рд╡реНрдпрд╛рдкреА" рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рдЧрд┐рд░рд╛рд╡рдЯред рдЗрд╕рд╕реЗ рдмрдЪрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ; рдореНрдпреВрдЯреЗрдХреНрд╕ рд╣рдорд╛рд░реЗ рд╕рдм рдХреБрдЫ рд╣реИрдВ ред

 template<class ...TParams> class TEvent { using TEventHandler = AbstractEventHandler<TParams...>; using TEventHandlerIt = typename std::list<TEventHandler*>::const_iterator; public: TEvent() : m_handlers(), m_currentIt(), m_isCurrentItRemoved( false ), m_handlerListMutex() { } void operator()( TParams... params ) { m_handlerListMutex.lock_shared(); m_isCurrentItRemoved = false; m_currentIt = m_handlers.begin(); while( m_currentIt != m_handlers.end() ) { m_handlerListMutex.unlock_shared(); ( *m_currentIt )->call( params... ); m_handlerListMutex.lock_shared(); if( m_isCurrentItRemoved ) { m_isCurrentItRemoved = false; TEventHandlerIt removedIt = m_currentIt; ++m_currentIt; deleteHandler( removedIt ); } else { ++m_currentIt; } } m_handlerListMutex.unlock_shared(); } bool operator+=( TEventHandler& eventHandler ) { std::unique_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); if( findEventHandler( eventHandler ) == m_handlers.end() ) { m_handlers.push_back( std::move( eventHandler ) ); return true; } return false; } bool operator-=( TEventHandler& eventHandler ) { std::unique_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); auto it = findEventHandler( eventHandler ); if( it != m_handlers.end() ) { if( it == m_currentIt ) m_isCurrentItRemoved = true; else deleteHandler( it ); return true; } return false; } private: //      'm_handlerListMutex' inline TEventHandlerIt findEventHandler( TEventHandler& eventHandler ) const { return std::find_if( m_handlers.cbegin(), m_handlers.cend(), [ &eventHandler ]( const TEventHandler* oneHandler ) { return ( *oneHandler == eventHandler ); } ); } //      'm_handlerListMutex' inline void deleteHandler( TEventHandlerIt it ) { TEventHandler* removedEventHandler = *it; m_handlers.erase( it ); delete removedEventHandler; } std::list<TEventHandler*> m_handlers; //    'm_handlerListMutex' mutable TEventHandlerIt m_currentIt; mutable bool m_isCurrentItRemoved; mutable std::shared_mutex m_handlerListMutex; }; 

рдЬрдм рднреА рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЦрд┐рдбрд╝рдХреА рдХреЛ рд▓рдЧрднрдЧ рд╣рд░ рдмрд╛рд░ рдЦреБрд▓рд╛ рдЫреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рддрд╛рдХрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдЧрддрд┐рд░реЛрдз рдХреЗ рдИрд╡реЗрдВрдЯ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдирд╛ рдФрд░ рдЙрд╕реЗ рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реЛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЬреЛрдбрд╝рдирд╛ / рд╣рдЯрд╛рдирд╛)ред рдЖрдк рдбреЗрдЯрд╛ рдХреА рд╡реИрдзрддрд╛ рд╕реЗ рдбрд░ рдирд╣реАрдВ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдореЗрдВ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ, рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдЗрд╕реЗ рд▓реЗ рдЬрд╛рддреА рд╣реИ рд╡рд╣ рд╡рд░реНрддрдорд╛рди рддрддреНрд╡ рдХрд╛ рд╡рд┐рд▓реЛрдкрди рд╣реИ, рдФрд░ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
UPD1ред рдзрдиреНрдпрд╡рд╛рдж рдЪреАрдЯрд░ , рдиреЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдХрд┐ std :: рд╕рд╛рдЭрд╛_рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗрд╡рд▓ C ++ 17 рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ (рдФрд░ std :: share_lock рдХреЗрд╡рд▓ C ++ 14 рдореЗрдВ )ред рдЬрд┐рдирдХреЗ рд▓рд┐рдП рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдЙрдиреНрд╣реЗрдВ рд╢рд╛рдпрдж std :: mutex рдХреЗ рд╕рд╛рде рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
UPD2ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдзрд╛рдЧрд╛ рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ (рдХрдерди рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛)ред

рдШрдЯрдирд╛ рджреГрд╢реНрдпрддрд╛ рд╕рдорд╕реНрдпрд╛


рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреЛ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рджрд╕реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЗрд╕реЗ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХрд░рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд▓рдЧрддрд╛ рд╣реИ, рддрд╛рдХрд┐ рддреГрддреАрдп-рдкрдХреНрд╖ рдСрдмреНрдЬреЗрдХреНрдЯ рдЕрдкрдиреЗ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝ / рдирд┐рдХрд╛рд▓ рд╕рдХреЗрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдСрдкрд░реЗрдЯрд░ () рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рджреЗрдЧрд╛, рдЕрд░реНрдерд╛рддред рдИрд╡реЗрдВрдЯ рдХреЙрд▓ рдмрд╛рд╣рд░ рд╕реЗ рднреА рд╕реБрд▓рдн рд╣реЛрдЧреА, рдЬреЛ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реЛ рд╕рдХрддреА рд╣реИред рд╣рдо рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдИрд╡реЗрдВрдЯ рдХреНрд▓рд╛рд╕ ( TEvent <...> ) рд╕реЗ рдЕрд▓рдЧ рдХрд░рдХреЗ рдХреЗрд╡рд▓ рд╕рд╛рд░ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рдкреНрд░реЗрд░рд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╣рд▓ рдХрд░реЗрдВрдЧреЗред

 template<class ...TParams> class IEvent { protected: using TEventHandler = AbstractEventHandler<TParams...>; public: bool operator+=( TEventHandler& eventHandler ) { return addHandler( eventHandler ); } bool operator-=( TEventHandler& eventHandler ) { return removeHandler( eventHandler ); } protected: IEvent() {} virtual bool addHandler( TEventHandler& eventHandler ) = 0; virtual bool removeHandler( TEventHandler& eventHandler ) = 0; }; 

 template<class ...TParams> class TEvent : public IEvent<TParams...> { . . . public: TEvent() : IEvent<TParams...>() . . . { } protected: virtual bool addHandler( TEventHandler& eventHandler ) override { // ,     'TEvent::operator+=' } virtual bool removeHandler( TEventHandler& eventHandler ) override { // ,     'TEvent::operator-=' } . . . }; 

рдЕрдм рд╣рдо рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реНрдХреЛрдк рдореЗрдВ рдЙрд╕ рдШрдЯрдирд╛ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╣реИрдВрдбрд▓рд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ, рдФрд░ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛ рдЬреЛ рдЗрд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред

 class TestWindow { . . . public: TestWindow() : onButtonClick( m_onButtonClick ), m_onButtonClick() { } IEvent<const std::string&, unsigned int>& onButtonClick; protected: TEvent<const std::string&, unsigned int> m_onButtonClick; . . . }; 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЕрдм рддреГрддреАрдп-рдкрдХреНрд╖ рдСрдмреНрдЬреЗрдХреНрдЯ TestWindow :: onButtonClick рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдкрдиреЗ рд╣реИрдВрдбрд▓рд░реНрд╕ рдХреЛ рдЬреЛрдбрд╝ / рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реЗ рд╕реНрд╡рдпрдВ рдЗрд╕ рдШрдЯрдирд╛ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗред рдПрдХ рдХреЙрд▓ рдЕрдм рдХреЗрд╡рд▓ TestWindow рд╡рд░реНрдЧ (рдФрд░ рдЗрд╕рдХреЗ рд╡рдВрд╢рдЬ, рдЕрдЧрд░ рдШрдЯрдирд╛ рдХреЗ рджрд╛рдпрд░реЗ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрд░рдХреНрд╖рд┐рдд рд╣реИ ) рдХреЗ рдЕрдВрджрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рддреБрдЪреНрдЫ рдХреЛрдб рдзреАрд░реЗ-рдзреАрд░реЗ рдХреБрдЫ рд░рд╛рдХреНрд╖рд╕реА рдореЗрдВ рдмрджрд▓рдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдВрдд рдирд╣реАрдВ рд╣реИред

рдореИрдЪ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдФрд░ рдЙрд╕рдХреЗ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рд╕реЗ рдорд┐рд▓рд╛рди рдХрд░реЗрдВ


рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдШрдЯрдирд╛ рдФрд░ рдЙрд╕рдХреЗ рдХрд┐рд╕реА рднреА рд╣реИрдВрдбрд▓рд░ рдХреЗ рдкрд╛рд╕ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдПрдХ рд╕рдЦреНрдд рд╕рдВрдЧрдд рд╕реВрдЪреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд╕реЗ рдХрдИ рдиреБрдХрд╕рд╛рди рд╣реЛрддреЗ рд╣реИрдВред

рдкрд╣рд▓рд╛ рд╡рд╛рд▓рд╛ред рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдХреНрд▓рд╛рд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдШрдЯрдирд╛ рд╣реИред

 template<class TSource> class MyClass { . . . public: TEvent<const TSource&> onValueChanged; . . . }; 

рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рдпрд╣рд╛рдВ рдЬрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рдЬреНрдЮрд╛рдд рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдирд┐рд░рдВрддрд░ рд▓рд┐рдВрдХ рджреНрд╡рд╛рд░рд╛ рдЗрд╕реЗ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдФрд░ рдореВрд▓реНрдп рд╕реЗ рдирд╣реАрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдм рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдореМрд▓рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде, рд╕рдВрдЧрдд рд╣реИрдВрдбрд▓рд░ рдореМрдЬреВрдж рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

 MyClass<bool> myBoolClass; . . . template<class TSource> class MyHandlerClass { . . . private: void handleValueChanged1( const bool& newValue ); void handleValueChanged2( bool newValue ); . . . }; . . . MyHandlerClass myHandlerClass; myBoolClass.onValueChanged += METHOD_HANDLER( myHandlerClass, MyHandlerClass::handleValueChanged1 ); // OK myBoolClass.onValueChanged += METHOD_HANDLER( myHandlerClass, MyHandlerClass::handleValueChanged2 ); // compile error 

рдореИрдВ рдкреНрд░рдкрддреНрд░ MyHandlerClass :: рд╣реИрдВрдбрд▓ValueChanged2 рдХреЗ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдПрдХ рд╕рдорд╛рди рдШрдЯрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ , рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдРрд╕реА рдХреЛрдИ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред

рджреВрд╕рд░рд╛ рд╡рд╛рд▓рд╛ред рдЖрдЗрдП рдПрдХ рдореМрдЬреВрджрд╛ рд╣реИрдВрдбрд▓рд░-рд╡рд┐рдзрд┐ (-рдПрдХ рд╡рд░реНрдЧ рдХреЗ -function-рд╕рджрд╕реНрдп) рдХреЗ рд╕рдорд╛рди рдПрдХ рдлрдВрдХреНрд╢рдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред

 template<class TFunctor, class ...TParams> class FunctorEventHandler : public AbstractEventHandler<TParams...> { public: FunctorEventHandler( TFunctor& functor ) : AbstractEventHandler<TParams...>(), m_functor( functor ) { } virtual void call( TParams... params ) override final { m_functor( params... ); } private: TFunctor& m_functor; }; template<class TFunctor, class ...TParams> AbstractEventHandler<TParams...>& createFunctorEventHandler( TFunctor&& functor ) { return *new FunctorEventHandler<TFunctor, TParams...>( functor ); } #define FUNCTOR_HANDLER( Functor ) createFunctorEventHandler( Functor ) 

рдЕрдм рдЗрд╕реЗ рдХрд┐рд╕реА рдШрдЯрдирд╛ рд╕реЗ рдорд┐рд▓рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред

 class TestWindow { . . . public: TEvent<const std::string&, unsigned int> onButtonClick; . . . }; struct ClickEventHandler { void operator()( const std::string&, unsigned int ) { . . . } }; int main( int argc, char *argv[] ) { . . . TestWindow testWindow; ClickEventHandler clickEventHandler; testWindow.onButtonClick += FUNCTOR_HANDLER( clickEventHandler ); . . . } 

рдкрд░рд┐рдгрд╛рдо рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреАред CreateFunctorEventHandler рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП , рдХрдВрдкрд╛рдЗрд▓рд░ TParams рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЕрдиреБрдорд╛рди рдирд╣реАрдВ рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реИ ... рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдПрдХрдорд╛рддреНрд░ рддрд░реНрдХ рд╕реЗ - рдлрд╝рдирдХрд╛рд░ рд╕реНрд╡рдпрдВред рдлрд╝рдирдХрд╛рд░ рдХреЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЙрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реИрдВрдбрд▓рд░ рдмрдирд╛рдирд╛ рд╣реИред рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рд╡рд╣ рд╣реИ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдирд╛:

 testWindow.onButtonClick += createFunctorEventHandler<ClickEventHandler, const std::string&, unsigned int>( clickEventHandler ); 

рд▓реЗрдХрд┐рди рдЖрдк рдРрд╕рд╛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдПрдХ рдШрдЯрдирд╛ рдХреЛ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рд╕реЗ рдЬреЛрдбрд╝рдирд╛


рддреЛ, рдПрдХ рд╡рд┐рд╢рд▓рд┐рд╕реНрдЯ рд╣реИ, рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реИред рд╣рдо рдПрдХ рдлрдВрдХреНрд╢рдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╕реНрдерд┐рддрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ; рдПрдХ рд╣реИрдВрдбрд▓рд░-рд╡рд┐рдзрд┐ (рдПрдХ рд╡рд░реНрдЧ рдХрд╛-рд╕рджрд╕реНрдп-рд╕рджрд╕реНрдп) рдПрдХ рд╕рдорд╛рди рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рдПрдЧреАред

рдЪреВрдВрдХрд┐ рдЕрдХреЗрд▓реЗ рдПрдХ рдлрд╝рдирдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдпрд╣ рдХрд╣рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рд╕реВрдЪреА рдХреНрдпрд╛ рд╣реЛрдЧреА, рдлрд┐рд░ рд╣рдо рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдкреНрд░рд╢реНрди рдЙрд╕ рд╕рдордп рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдШрдЯрдирд╛ рдореЗрдВ рдЗрд╕реЗ рд╕рдВрд▓рдЧреНрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреЗ рд╕рдордпред рдФрд░ рд╣рд╛рдВ, рдпреЗ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдмрд┐рдВрджреБ рд╣реИрдВред рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

 template<class TFunctor> class FunctorHolder; template<class TFunctor, class ...TParams> class FunctorEventHandler : public AbstractEventHandler<TParams...> { public: FunctorEventHandler( FunctorHolder<TFunctor>& functorHolder ) : AbstractEventHandler<TParams...>(), m_functorHolder( functorHolder ) { } virtual void call( TParams... params ) override { m_functorHolder.m_functor( params... ); } private: FunctorHolder<TFunctor>& m_functorHolder; . . . }; 

 template<class TFunctor> class FunctorHolder { public: FunctorHolder( TFunctor& functor ) : m_functor( functor ) { } template<class ...TCallParams> operator AbstractEventHandler<TCallParams...>&() { return *new FunctorEventHandler<TFunctor, TCallParams...>( *this ); } private: TFunctor& m_functor; . . . template<class TFunctor, class ...TParams> friend class FunctorEventHandler; }; 

 template<class TFunctor> FunctorHolder<TFunctor>& createFunctorEventHandler( TFunctor&& functor ) { return *new FunctorHolder<TFunctor>( functor ); } #define FUNCTOR_HANDLER( Functor ) createFunctorEventHandler( Functor ) #define LAMBDA_HANDLER( Lambda ) FUNCTOR_HANDLER( Lambda ) #define STD_FUNCTION_HANDLER( StdFunction ) FUNCTOR_HANDLER( StdFunction ) #define FUNCTION_HANDLER( Function ) FUNCTOR_HANDLER( &Function ) 

 template<class ...TParams> class IEvent { protected: using TEventHandler = AbstractEventHandler<TParams...>; public: template<class TSome> bool operator+=( TSome&& some ) { return addHandler( static_cast<TEventHandler&>( some ) ); } template<class TSome> bool operator-=( TSome&& some ) { return removeHandler( static_cast<TEventHandler&>( some ) ); } protected: IEvent() {} virtual bool addHandler( TEventHandler& eventHandler ) = 0; virtual bool removeHandler( TEventHandler& eventHandler ) = 0; }; 

рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рд╣реИрдВрдбрд▓рд░ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдХреНрд╖рдгреЛрдВ рдХреА рдЬреБрджрд╛рдИ рдФрд░ рдпрд╣рд╛рдВ рдХреА рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рд▓рдЧрд╛рд╡ рдкрд╣рд▓реЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд╣реИред рдпрд╣ рдкрд┐рдЫрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЯрд╛рдЗрдк рдлрд╝рдВрдХреНрд╢рдВрд╕ рдЯреЗрд╕реНрдЯрд┐рдВрдЧ рддрдм рд╣реЛрдЧреА рдЬрдм рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлрд╝рдВрдХреНрд╢рдирд▓рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлрд╝рдВрдХреНрд╢рдирд▓рд╣реИрдВрдбрд▓рд░ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ, рдпрд╛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдлрд╝рдВрдХреНрд╢рдирд▓рдЗрд╡реЗрдВрдЯрд╣реИрдВрдбрд▓рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдПрдВ <...> рдПрдХ рдмрд╣реБрдд рд╣реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлрд╝рдВрдХреНрдЯрд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧ; рдФрд░ рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рдХреЛрдб m_functorHolder.m_functor (params ...) рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реЛрдЧреА ; , рдЬреЛ рдмрд╕ рдПрдХ рдлрд╝рдирдХрд╛рд░ рдХреЗ рд╕рд╛рде рдЕрд╕рдВрдЧрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реЗрдЯ рдХреЗ рд▓рд┐рдП рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдпрд╛ рдпрджрд┐ рдпрд╣ рдПрдХ рдлрд╝рдирдХрд╛рд░ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рд╣реИ, рдЕрд░реНрдерд╛рдд рдРрд╕реА рд╡рд╕реНрддреБ рдЬрд┐рд╕рдореЗрдВ рдСрдкрд░реЗрдЯрд░ рдирд╣реАрдВ рд╣реИ () )ред

рдореИрдВ рджреЛрд╣рд░рд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдЕрд╕реНрдерд╛рдпреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдкрд░ рдиреАрдЪреЗ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдореИрдХреНрд░реЛрдЬрд╝ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВрдбрд▓рд░реНрд╕ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рдлрд╝рд╛рдЗрд▓ рджреНрд╡рд╛рд░рд╛ рдЙрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдВрд╢реЛрдзрди рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВред

рдкрд░рд┐рдгрд╛рдо рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВред

 class TestWindow { . . . public: TEvent<const std::string&, unsigned int> onButtonClick; . . . }; struct Functor { void operator()( const std::string&, unsigned int ) {} }; struct Functor2 { void operator()( std::string, unsigned int ) {} }; struct Functor3 { void operator()( const std::string&, const unsigned int& ) {} }; struct Functor4 { void operator()( std::string, const unsigned int& ) {} }; struct Functor5 { void operator()( std::string&, unsigned int& ) {} }; struct Functor6 { void operator()( const std::string&, unsigned int& ) {} }; struct Functor7 { void operator()( std::string&, const unsigned int& ) {} }; int main( int argc, char *argv[] ) { . . . TestWindow testWindow; Functor functor; Functor2 functor2; Functor3 functor3; Functor4 functor4; Functor5 functor5; Functor6 functor6; Functor7 functor7; testWindow.onButtonClick += FUNCTOR_HANDLER( functor ); // ok testWindow.onButtonClick += FUNCTOR_HANDLER( functor2 ); // ok testWindow.onButtonClick += FUNCTOR_HANDLER( functor3 ); // ok testWindow.onButtonClick += FUNCTOR_HANDLER( functor4 ); // ok testWindow.onButtonClick += FUNCTOR_HANDLER( functor5 ); // compile error testWindow.onButtonClick += FUNCTOR_HANDLER( functor6 ); // ok testWindow.onButtonClick += FUNCTOR_HANDLER( functor7 ); // compile error . . . } 

рдХреЙрдореНрдкреНрд▓реЗрдХреНрд╕ рд▓реИрд╡рд▓реНрдпреВ рд╕реЗ рд▓реЗрд╡рд▓реНрдпреВ рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╕рдордп рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИред рдЕрд╕рдВрдмрджреНрдз рдЕрдВрддрд░рд╛рд▓ рд╕реЗ рдЕрдВрддрд░рд╛рд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрдиреЗ рд╕реЗ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдпрд╣ рдкреИрд░ рдореЗрдВ рдЖрддреНрдо-рд╢реЙрдЯ рдХрд╛ рд╕рдВрднрд╛рд╡рд┐рдд рдЦрддрд░рд╛ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИ: рд╣реИрдВрдбрд▓рд░ рд╕реНрдЯреИрдХ рдкрд░ рдХреЙрдкреА рдХрд┐рдП рдЧрдП рдЪрд░ рдХреЛ рдмрджрд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛, рдЬреЛ рдЗрд╕ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдкрд░ рдЦреБрд╢реА рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

 Error C2664 'void Functor5::operator ()(std::string &,unsigned int &)': cannot convert argument 1 from 'const std::string' to 'std::string &' 

рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП, рддреГрддреАрдп-рдкрдХреНрд╖ рдХреЛрдб рдореЗрдВ рдИрд╡реЗрдВрдЯ рдФрд░ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдЕрдкрдиреА рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреА рд╕рд╣рд╛рдпрдХ рд╕рдВрд░рдЪрдирд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдВ, рдореИрдВрдиреЗ рдХрд╣реАрдВ рдЗрд╕реА рддрд░рд╣ рдХрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рд╣реИ):

 namespace { template<class TFunctor, class ...TParams> struct IsFunctorParamsCompatible { private: template<class TCheckedFunctor, class ...TCheckedParams> static constexpr std::true_type exists( decltype( std::declval<TCheckedFunctor>()( std::declval<TCheckedParams>()... ) )* = nullptr ); template<class TCheckedFunctor, class ...TCheckedParams> static constexpr std::false_type exists( ... ); public: static constexpr bool value = decltype( exists<TFunctor, TParams...>( nullptr ) )::value; }; } // 

 template<class TFunctor, class ...TParams> class FunctorEventHandler : public AbstractEventHandler<TParams...> { . . . public: virtual void call( TParams... params ) override { static_assert( IsFunctorParamsCompatible<TFunctor, TParams...>::value, "Event and functor arguments are not compatible" ); m_functorHolder->m_functor( params... ); } . . . }; 

рдпрд╣ рдХрд╛рдо SFINAE рддрдВрддреНрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ , рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рдпрд╣ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреА рдЕрд╕рдВрдЧрддрддрд╛ (рдпрд╛ рдСрдкрд░реЗрдЯрд░ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рд╕реЗ рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рдХрд╛рд░рдг рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ), рдЬреЛ рдлреЙрд▓рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рд╣реЛ рдЧрдпрд╛ рдерд╛), рд╕рдВрдХрд▓рдХ рдПрдХ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдлреЗрдВрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╕ рджреВрд╕рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ; рд╣рдо рд╕рдм рдХреБрдЫ рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдЗрд╕рдХрд╛ рд╕рдВрдХрд▓рди рд╣рдореЗрд╢рд╛ рд╕рдлрд▓ рд╣реЛ, рдФрд░ рдлрд┐рд░, рдЗрд╕ рддрдереНрдп рдкрд░ рдХрд┐ рдХрд┐рд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╣рдо рджрд┐рдП рдЧрдП рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рддрд░реНрдХреЛрдВ рдХреА рд╕рдВрдЧрддрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВред

рдЕрдм рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:

 Error C2338 Event and functor arguments are not compatible Error C2664 'void Functor5::operator ()(std::string &,unsigned int &)': cannot convert argument 1 from 'const std::string' to 'std::string &' 

рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд, рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рддрд░реНрдХ (рдУрдВ) рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЕрд╕рдВрдмрджреНрдз рдЕрдВрддрд░рд╛рд▓ рд╕реЗ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ: рдЕрдм рдпрд╣ рддрд░реНрдХ рдЕрд╕рдВрдЧрддрддрд╛ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд рд╕рдВрдХрд▓рди-рдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐ рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рдХреЗ рдКрдкрд░ рдЙрджрд╛рд╣рд░рдг рд╕реЗ functor6 рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ ред
рдпреБрдкреАрдбреАред рд╢реЛрдзрди (рдХрдерди рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛)ред

рдлрд╝рдирдХрд╛рд░ рддреБрд▓рдирд╛


рд╣реИрдВрдбрд▓рд░ рд╡рд░реНрдЧ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдХрд╛рд░рдг, рдЗрд╕ рд╡рд░реНрдЧ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдереЛрдбрд╝рд╛ рдмрджрд▓ рдЬрд╛рдПрдЧрд╛ред рдПрдХ рдмрд╛рд░ рдлрд┐рд░, рдореИрдВ рдХреЗрд╡рд▓ рдПрдХ рдлрдВрдХреНрд╢рдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдкреНрд░рджрд╛рди рдХрд░реВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╣реИрдВрдбрд▓рд░-рд╡рд┐рдзрд┐ (рд╡рд░реНрдЧ рдХреЗ -function- рд╕рджрд╕реНрдп) рд╕рдорд╛рди рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред

 template<class ...TParams> class AbstractEventHandler { . . . using MyType = AbstractEventHandler<TParams...>; public: bool operator==( const MyType& other ) const { return isEquals( other ); } bool operator!=( const MyType& other ) const { return !( *this == other ); } protected: virtual bool isEquals( const MyType& other ) const = 0; . . . }; 

 template<class TFunctor, class ...TParams> class FunctorEventHandler : public AbstractEventHandler<TParams...> { . . . using MyType = FunctorEventHandler<TFunctor, TParams...>; protected: virtual bool isEquals( const AbstractEventHandler<TParams...>& other ) const override { const MyType* _other = dynamic_cast<const MyType*>( &other ); return ( _other != nullptr && *m_functorHolder == *_other->m_functorHolder ); } private: FunctorHolder<TFunctor>& m_functorHolder; . . . }; 

 template<class TFunctor> class FunctorHolder { . . . using MyType = FunctorHolder<TFunctor>; public: bool operator==( const MyType& other ) const { return ( m_functor == other.m_functor ); } bool operator!=( const MyType& other ) const { return !( *this == other ); } private: TFunctor& m_functor; . . . }; 

рдЗрд╕ рдкрд░, рддреБрд▓рдирд╛рддреНрдордХ рдЕрдВрдд рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╕рдорд╛рдирддрд╛ рдФрд░ рд╣рд┐рд╕реНрд╕рд╛ рдХреЗрд╡рд▓ рдлрдВрдХреНрд╢рдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд▓рд┐рдП рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред

рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдордиреЗ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдлрд╝рдВрдХреНрд╢рдирд▓ рд╣реИрдВрдбрд▓рд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рд╣реИрдВ: рд╕реАрдзреЗ рдлрд╝рдВрдХреНрд╢рдирд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕, рд▓реИрдореНрдмреНрдбрд╛ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди, рдПрд╕рдЯреАрдбреА рдХреЗ рдЙрджрд╛рд╣рд░рдг :: рдлрд╝рдВрдХреНрд╢рди рдХреНрд▓рд╛рд╕, рд╡реНрдпрдХреНрддрд┐рдЧрдд рдлрд╝рдВрдХреНрд╢рдиред рдЗрдирдореЗрдВ рд╕реЗ, рдлрд╝рдиреНрдиреЗрдЯрд░ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕, рд▓реИрдореНрдмреНрдбрд╛ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдФрд░ std рдХреЗ рдЙрджрд╛рд╣рд░рдг :: рдлрдВрдХреНрд╢рди рдХреНрд▓рд╛рд╕ рдХреА рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░ == рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ (рдЙрдиреНрд╣реЗрдВ рдкрддреЗ рдкрд░ рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ), рд▓реЗрдХрд┐рди рд╡реНрдпрдХреНрддрд┐рдЧрдд рдХрд╛рд░реНрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдВрдЧреНрд░рд╣рд┐рдд рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╕реЗ рддреБрд▓рдирд╛ рд╕рдорд╛рд░реЛрд╣ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ, рд╣рдо рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:

 namespace { template<class TEqu, class TEnabled = void> struct EqualityChecker; template<class TEquatable> struct EqualityChecker<TEquatable, typename std::enable_if<is_equatable<TEquatable>::value>::type> { static constexpr bool isEquals( const TEquatable& operand1, const TEquatable& operand2 ) { return ( operand1 == operand2 ); } }; template<class TNonEquatable> struct EqualityChecker<TNonEquatable, typename std::enable_if<!is_equatable<TNonEquatable>::value>::type> { static constexpr bool isEquals( const TNonEquatable& operand1, const TNonEquatable& operand2 ) { return ( &operand1 == &operand2 ); } }; } // template<class TFunctor> class FunctorHolder { . . . using MyType = FunctorHolder<TFunctor>; public: bool operator==( const MyType& other ) const { return EqualityChecker<TFunctor>::isEquals( m_functor, other.m_functor ); } private: TFunctor& m_functor; . . . }; 

рдпрд╣ рд╕рдордЭрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ is_equitable рдПрдХ рд╕рд╣рд╛рдпрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИ рдЬреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдкреНрд░рдХрд╛рд░ рдХреЗ рджреЛ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рд╕рдорд╛рдирддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЗрд╕рдХреА рдорджрдж рд╕реЗ, std :: enable_if рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП , рд╣рдо рджреЛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЗрдХреНрд╡рд▓рд┐рдЯреАрдХреИрдЪрд░ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ , рдЬреЛ рдПрдХ рддреБрд▓рдирд╛ рдХрд╛ рд╕рдВрдЪрд╛рд▓рди рдХрд░реЗрдЧрд╛: рдореВрд▓реНрдп рджреНрд╡рд╛рд░рд╛ рдпрд╛ рдкрддреЗ рд╕реЗред Is_equitable рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ , рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддреА рд╣реИ:

 template<class T> class is_equatable { private: template<class U> static constexpr std::true_type exists( decltype( std::declval<U>() == std::declval<U>() )* = nullptr ); template<class U> static constexpr std::false_type exists( ... ); public: static constexpr bool value = decltype( exists<T>( nullptr ) )::value; }; 

рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди SFINAE рддрдВрддреНрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ , рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд╣рд▓реЗ рд╣реА рдХрд┐рдпрд╛ рдЬрд╛ рдЪреБрдХрд╛ рд╣реИ ред рдХреЗрд╡рд▓ рдпрд╣рд╛рдБ рд╣рдо рдПрдХ рджрд┐рдП рдЧрдП рд╡рд░реНрдЧ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдСрдкрд░реЗрдЯрд░ == рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ ред

рдЗрд╕ рд╕рд░рд▓ рддрд░реАрдХреЗ рд╕реЗ, рд╣реИрдВрдбрд▓рд░-рдлрдВрдХреНрд╢рдирд▓рд░реНрд╕ рдХреА рддреБрд▓рдирд╛ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рддреИрдпрд╛рд░ рд╣реИред

рдХрдЪрд░рд╛ рд╕рдВрдЧреНрд░рд╣


рдЙрджрд╛рд░ рдмрдиреЛ, рдореИрдВ рднреА рдПрдХ рдЬреЛрд░ рд╕реЗ рд╢реАрд░реНрд╖рдХ рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред

рд╣рдо рд╕рдорд╛рдкрди рдХреЗ рдХрд░реАрдм рдкрд╣реБрдВрдЪ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмрдирд╛рдИ рдЧрдИ рд╡рд╕реНрддреБрдУрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ рдЬрд┐рд╕реЗ рдХреЛрдИ рднреА рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╕рд╛рде рдкреНрд░рддреНрдпреЗрдХ рдИрд╡реЗрдВрдЯ рдПрдХреНрд╢рди рджреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИ: рд╣реЛрд▓реНрдбрд░ , рдЬреЛ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рднрд╛рдЧ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ EventHandlerрдЗрд╕реЗ рдШрдЯрдирд╛ рд╕реЗ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реИред рд╣рдо рдпрд╣ рдирд╣реАрдВ рднреВрд▓реЗрдВрдЧреЗ рдХрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдХреЛрдИ рдЬреЛрдбрд╝ рдирд╣реАрдВ рд╣реЛрдЧрд╛ - рджреЛ рд╡рд╕реНрддреБрдПрдВ "рд╣рд╡рд╛ рдореЗрдВ рдирд┐рд▓рдВрдмрд┐рдд" рд╣реИрдВ (рдЬрдм рддрдХ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ рд╣рд░ рдмрд╛рд░ рдЕрд▓рдЧ рд╕реЗ рдЬрд╛рдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдПрдХ рдФрд░ рд╕реНрдерд┐рддрд┐: рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╣рдЯрд╛рдирд╛; рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреА рд╕реВрдЪреА рдореЗрдВ рд╕рдорд╛рди (рд╕рдорд╛рди) рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рджреЛ рдирдП рдСрдмреНрдЬреЗрдХреНрдЯ рднреА рдмрдирд╛рдП рдЧрдП рд╣реИрдВ; рд╕реВрдЪреА рдореЗрдВ рдкрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИрдВрдбрд▓рд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдпрджрд┐ рдХреЛрдИ рд╣реЛ), рдФрд░ рдпрд╣ рдЕрд╕реНрдерд╛рдпреА рдПрдХ, рдЬреЛ рджреЛ рд╡рд╕реНрддреБрдУрдВ рдХреА рдЦреЛрдЬ рдФрд░ рд╕рдореНтАНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдлрд┐рд░ рд╕реЗ "рд╣рд╡рд╛ рдореЗрдВ" рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╢рд╛рдВрдд рдирд╣реАрдВред рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреА рдУрд░

рдореБрдбрд╝реЗрдВ ред рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рджреЛ рд╣реИрдВрдбрд▓рд░ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдХрд╛ рд╢рдмреНрджрд╛рд░реНрде рдХреНрдпрд╛ рд╣реЛрдЧрд╛: рдПрдХрдорд╛рддреНрд░ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ ( std :: unique_ptr ) рдпрд╛ рд╕рд╛рдЭрд╛ ( std :: рд╕рд╛рдЭрд╛_ptr )ред рдзрд╛рд░рдХ

рдЬреЛрдбрд╝рддреЗ / рд╣рдЯрд╛рддреЗ рд╕рдордп рд╕реНрд╡рдпрдВ рдЗрд╡реЗрдВрдЯ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдЕрд▓рд╛рд╡рд╛, EventHandler рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП , рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕рд╛рдЭрд╛ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ EventHandler рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХрдорд╛рддреНрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рдж, рдпрд╣ рдХреЗрд╡рд▓ рдШрдЯрдирд╛ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХрд╛ рдПрд╣рд╕рд╛рд╕ рд╣реИ:

 template<class ...TParams> class AbstractEventHandler { . . . public: virtual ~AbstractEventHandler() {} . . . }; template<class ...Types> using THandlerPtr = std::unique_ptr<AbstractEventHandler<Types...>>; 

 namespace { template<class TSome> struct HandlerCast { template<class ...Types> static constexpr THandlerPtr<Types...> cast( TSome& some ) { return static_cast<THandlerPtr<Types...>>( some ); } }; template<class TPtr> struct HandlerCast<std::shared_ptr<TPtr>> { template<class ...Types> static constexpr THandlerPtr<Types...> cast( std::shared_ptr<TPtr> some ) { return HandlerCast<TPtr>::cast<Types...>( *some ); } }; } // template<class ...TParams> class IEvent { public: template<class TSome> bool operator+=( TSome&& some ) { return addHandler( HandlerCast<TSome>::cast<TParams...>( some ) ); } template<class TSome> bool operator-=( TSome&& some ) { return removeHandler( HandlerCast<TSome>::cast<TParams...>( some ) ); } protected: using TEventHandlerPtr = THandlerPtr<TParams...>; IEvent() {} virtual bool addHandler( TEventHandlerPtr eventHandler ) = 0; virtual bool removeHandler( TEventHandlerPtr eventHandler ) = 0; }; template<class ...TParams> class TEvent : public IEvent<TParams...> { using TEventHandlerIt = typename std::list<TEventHandlerPtr>::const_iterator; public: TEvent() { . . . } ~TEvent() { // empty } protected: virtual bool addHandler( TEventHandlerPtr eventHandler ) override { std::unique_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); if( findEventHandler( eventHandler ) == m_handlers.end() ) { m_handlers.push_back( std::move( eventHandler ) ); return true; } return false; } virtual bool removeHandler( TEventHandlerPtr eventHandler ) override { . . . } private: //      'm_handlerListMutex' inline TEventHandlerIt findEventHandler( const TEventHandlerPtr& eventHandler ) const { return std::find_if( m_handlers.cbegin(), m_handlers.cend(), [ &eventHandler ]( const TEventHandlerPtr& oneHandler ) { return ( *oneHandler == *eventHandler ); } ); } //      'm_handlerListMutex' inline void deleteHandler( TEventHandlerIt it ) { m_handlers.erase( it ); } std::list<TEventHandlerPtr> m_handlers; . . . }; 

 template<class TMethodHolder, class ...TParams> class MethodEventHandler : public AbstractEventHandler<TParams...> { . . . using TMethodHolderPtr = std::shared_ptr<TMethodHolder>; public: MethodEventHandler( TMethodHolderPtr methodHolder ) : AbstractEventHandler<TParams...>(), m_methodHolder( methodHolder ) { assert( m_methodHolder != nullptr ); } private: TMethodHolderPtr m_methodHolder; . . . }; template<class TObject, class ...TParams> class MethodHolder { using MyType = MethodHolder<TObject, TParams...>; using TMethod = void( TObject::* )( TParams... ); public: MethodHolder( TObject& object, TMethod method ) { . . . } template<class ...TCallParams> operator THandlerPtr<TCallParams...>() { return THandlerPtr<TCallParams...>( new MethodEventHandler<MyType, TCallParams...>( /*   ? */ ) ); } . . . }; template<class TObject, class ...TParams> std::shared_ptr<MethodHolder<TObject, TParams...>> createMethodEventHandler( TObject& object, void( TObject::*method )( TParams... ) ) { return std::shared_ptr<MethodHolder<TObject, TParams...>>( new MethodHolder<TObject, TParams...>( object, method ) ); } #define METHOD_HANDLER( Object, Method ) createMethodEventHandler( Object, &Method ) #define MY_METHOD_HANDLER( Method ) METHOD_HANDLER( *this, Method ) 

рдкрд╣рд▓реЗ рдЪреАрдЬреЗрдВ рдкрд╣рд▓реЗред

рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣реИрдВрдбрд▓рд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдШрдЯрдирд╛ рдФрд░ рдЗрд╕рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ред рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рдореЗрдВ, рдЖрдк рдЕрдм static_cast рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реАрдзреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ , рдХреНрдпреЛрдВрдХрд┐ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдкреНрд░рдХрд╛рд░ рдЭреВрда "рдЕрдВрджрд░" std :: рд╕рд╛рдЭрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рдЕрдм рдЗрд╕ рддрд░рд╣ рдХреЗ рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рд╣рд╛рдпрдХ рд╣реИрдВрдбрд▓рд░рдХреИрд╕реНрдЯ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ , рдЬреЛ рдХрд┐ рдЗрд╕рдХреЗ рдирд┐рдЬреА рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рджреНрд╡рд╛рд░рд╛, std :: рд╕рд╛рдЭрд╛_ptr рдХреЗ рдЕрдВрджрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ , рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ (рдЗрд╕рдХреЗ рдЧреИрд░-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ), рдпрд╣ рдЕрдЪреНрдЫреЗ рдкреБрд░рд╛рдиреЗ static_cast рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧрд╛ ред

рдШрдЯрдирд╛ рд╕реНрд╡рдпрдВ; рдпрд╣рд╛рдВ рдХрдИ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрджрд▓рд╛рд╡ рднреА рд╣реБрдП рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рдЗрдВрд╕реНрдЯреЗрдВрд╕реЗрд╕ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╣рдЯрд╛рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рджреМрд░рд╛рди рд░реЛрдХреЗрдВрдЧреЗ; рдЕрдм рд╕реВрдЪреА рд╕реЗ рдЗрд╕ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╕рд╛рде рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рд╣рдЯрд╛рдирд╛ рдХрд╛рдлреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдм рдПрдХ рд╣реИрдВрдбрд▓рд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ std рдХреЛ рди рднреВрд▓реЗрдВ :: рдЪрд╛рд▓ , рдХреНрдпреЛрдВрдХрд┐ std :: unique_ptr рдирдХрд▓ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдЬреЛ рдРрд╕реЗ рд╢рдмреНрджрд╛рд░реНрдереЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рддрд╛рд░реНрдХрд┐рдХ рд╣реИ)ред

рдЪрд▓реЛ рд╣реИрдВрдбрд▓рд░реНрд╕ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВред рдкреБрд░рд╛рдиреА рдкрд░рдВрдкрд░рд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдЙрдирдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рджреВрд╕рд░рд╛ рд╕рдорд╛рди рд╣реИред рдФрд░ рдпрд╣рд╛рдВ, рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдпрд╣ рд▓рд┐рдВрдХ / рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реЗ рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░реНрд╕ рддрдХ рд╕рдВрдЧреНрд░рд╣реАрдд / рдмрдирд╛рдИ рдЧрдИ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рдЖрддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдПрдХ рд╕реВрдХреНрд╖реНрдо рдмрд┐рдВрджреБ рд╣реИред рд╕рдорд╛рд░реЛрд╣ createMethodEventHandler рд╡рд╛рдкрд╕реА std :: shared_ptr рдЖрд╡реГрддреНрддрд┐рдореЗрдердб рдлреЛрд▓реНрдбрд░ ред рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж, рдЗрд╕реЗ рдПрдХ рд╣реИрдВрдбрд▓рд░ рдкреНрд░рдХрд╛рд░ ( рдореЗрдердПрд╡реЗрдВрдЯрд╣реИрдВрдбрд▓рд░ ) рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ , рдЬрд╣рд╛рдВ рдЗрд╕реЗ рдореЗрдердбрд╡реЗрдВрдЯрд╣реИрдВрдбрд▓рд░ рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ , рдЗрд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдПрд╕рдЯреАрдбреА рдкрд░ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ : рд╕рд╛рдЭрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╕реНрд╡рдпрдВ рдХреЗ рд▓рд┐рдПред рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ MethodHolder рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдмрд╛рдж рдореЗрдВ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬрдм MethodEventHandler рдЙрджрд╛рд╣рд░рдг рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рд▓реЗрдХрд┐рди рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ MethodHolder рдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рд░реНрдорд┐рдд std :: share_ptr рдХреА рдХреЛрдИ рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред

рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдореЗрдердб рдлреЛрд▓реНрдбрд░ рдореЗрдВ рдЦреБрдж рдХреЛ рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рддрд╛рдХрд┐ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдХрд╛рд╕рди рдкрд░ рдХреЛрдИ рдЕрд╕рд░ рди рдкрдбрд╝реЗ, рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВstd :: weak_ptr :

 template<class TObject, class ...TParams> class MethodHolder { using MyType = MethodHolder<TObject, TParams...>; using TMethod = void( TObject::* )( TParams... ); public: template<class ...TCallParams> operator THandlerPtr<TCallParams...>() { return THandlerPtr<TCallParams...>( new MethodEventHandler<MyType, TCallParams...>( m_me.lock() ) ); } template<class TObject, class ...TParams> static std::shared_ptr<MyType> create( TObject& object, TMethod method ) { std::shared_ptr<MyType> result( new MyType( object, method ) ); result->m_me = result; return result; } private: MethodHolder( TObject& object, TMethod method ) : m_object( object ), m_method( method ) { assert( m_method != nullptr ); } TObject& m_object; TMethod m_method; std::weak_ptr<MyType> m_me; }; template<class TObject, class ...TParams> std::shared_ptr<MethodHolder<TObject, TParams...>> createMethodEventHandler( TObject& object, void( TObject::*method )( TParams... ) ) { return MethodHolder<TObject, TParams...>::create( object, method ); } 

рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдХрд┐рд╕реА рдИрд╡реЗрдВрдЯ рд╕реЗ рдХрд┐рд╕реА рд╣реИрдВрдбрд▓рд░ рдХреЛ рдирд┐рдХрд╛рд▓рддреЗ рд╕рдордп рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЕрдиреБрдорд╛рдирд┐рдд рдХреНрд░рдо рджреЗ рджреВрдВрдЧрд╛ (рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдЬрд╛ рдХреЗ рд▓рд┐рдП рдореЗрд░реА рдорд╛рдлреА:)

  • рдЗрд╡реЗрдВрдЯ рд╕реВрдЪреА рд╕реЗ рдЖрдЗрдЯрдо рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реИ ( m_handlers.erase (рдпрд╣); ), рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рдЗрд╕рдХреЗ рд╡рд┐рдирд╛рд╢рдХрд░реНрддрд╛ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ;
  • рд╡рд┐рдзреНрд╡рдВрд╕рдХ std :: unique_ptr рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЬреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдХреЛ рдПрдХ рдХреЙрд▓ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ;
  • MethodEventHandler рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЬреЛ m_methodHolder рдлрд╝реАрд▓реНрдб рд╕рд╣рд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рднреА рдлрд╝реАрд▓реНрдб рдХреЛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИ , рдЬреЛ рдХрд┐ std :: share_ptr ;
  • std::shared_ptr ; , (.. ) ( MethodHolder ); , std::weak_ptr ;
  • MethodHolder , , , m_me , std::weak_ptr ;
  • std::weak_ptr ; ; .. std::weak_ptr , ;
  • рд▓рд╛рднред

рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ AbstractEventHandler рд╡рд░реНрдЧ рдХрд╛ рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдЖрднрд╛рд╕реА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП; рдЕрдиреНрдпрдерд╛, рдкреИрд░рд╛ рдХреЗ рдмрд╛рдж 2 рдкреИрд░рд╛ рдореЗрдВ 3 рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдирд╛рд╢рдХ рдХреЙрд▓ AbstractEventHandler рдФрд░ рдЖрдЧреЗ рдХреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХреА рдЬрд╛рдПрдЧреАред

рдШрдЯрдирд╛ рдФрд░ рд╣реИрдВрдбрд▓рд░ рдХрдиреЗрдХреНрд╢рди


рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЬрдм рдХрд┐рд╕реА рдШрдЯрдирд╛ рдореЗрдВ рдПрдХ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ / рд╣рдЯрд╛рдиреЗ рдХреЗ рджреМрд░рд╛рди рдЕрдХреНрд╕рд░ (рдХреБрдЫ рддрд░реНрдХ рдХреЗ рдЕрдиреБрд╕рд╛рд░) рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдкрд░реЗрд╢рд╛рди рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рд░ рдмрд╛рд░ рдШрдЯрдирд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдФрд░ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛, рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕реЗ рдЗрд╕ рдШрдЯрдирд╛ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ / рд╕рджрд╕реНрдпрддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ред рд▓реЗрдХрд┐рди рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдмрд╛рд░ рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдФрд░ рдлрд┐рд░, рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдПрдХ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдШрдЯрдирд╛ рд╕реЗ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ / рд╣рдЯрд╛рдиреЗ рдХреЗ рд╕рд╛рде, рдЗрд╕ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВред рдЖрдк рдЗрд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 template<class ...Types> using THandlerPtr = std::shared_ptr<AbstractEventHandler<Types...>>; 

 template<class ...TParams> class IEvent { . . . protected: using TEventHandlerPtr = THandlerPtr<TParams...>; virtual bool isHandlerAdded( const TEventHandlerPtr& eventHandler ) const = 0; virtual bool addHandler( TEventHandlerPtr eventHandler ) = 0; virtual bool removeHandler( TEventHandlerPtr eventHandler ) = 0; friend class HandlerEventJoin<TParams...>; . . . }; template<class ...TParams> class TEvent : public IEvent<TParams...> { . . . protected: virtual bool isHandlerAdded( const TEventHandlerPtr& eventHandler ) const override { std::shared_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); return ( findEventHandler( eventHandler ) != m_handlers.end() ); } virtual bool addHandler( TEventHandlerPtr eventHandler ) override { . . . } virtual bool removeHandler( TEventHandlerPtr eventHandler ) override { . . . } private: //      'm_handlerListMutex' inline TEventHandlerIt findEventHandler( const TEventHandlerPtr& eventHandler ) const { . . . } std::list<TEventHandlerPtr> m_handlers; mutable std::shared_mutex m_handlerListMutex; . . . }; 

 template<class ...TParams> class HandlerEventJoin { public: HandlerEventJoin( IEvent<TParams...>& _event, THandlerPtr<TParams...> handler ) : m_event( _event ), m_handler( handler ) { } inline bool isJoined() const { return m_event.isHandlerAdded( m_handler ); } inline bool join() { return m_event.addHandler( m_handler ); } inline bool unjoin() { return m_event.removeHandler( m_handler ); } private: IEvent<TParams...>& m_event; THandlerPtr<TParams...> m_handler; }; 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдм рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╕рдВрднрд╛рд╡рд┐рдд рд╕реНрдерд╛рди рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП std :: unique_ptr рдХреЗ рдмрдЬрд╛рдп std :: shared_ptr рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рд╡рд░реНрдЧ, рдореЗрд░реЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдореИрдВ рдЙрди рдорд╛рдирдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рдмрд┐рдирд╛ рдХрдиреЗрдХреНрд╢рди рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЛ рд╕реНрдЯреЛрд░ рдФрд░ рдХреНрд░рд┐рдПрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдХреНрд▓рд╛рд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдЗрдВрд╕реНрдЯреЗрдВрдЯ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдПрдХ рдЕрдореВрд░реНрдд рдкреВрд░реНрд╡рдЬ рд╡рд░реНрдЧ рдФрд░ рдЖрд╡рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:





 class AbstractEventJoin { public: virtual ~AbstractEventJoin() {} virtual bool isJoined() const = 0; virtual bool join() = 0; virtual bool unjoin() = 0; protected: AbstractEventJoin() {} }; 

 template<class ...TParams> class HandlerEventJoin : public AbstractEventJoin { . . . public: virtual inline bool isJoined() const override { . . . } virtual inline bool join() override { . . . } virtual inline bool unjoin() override { . . . } . . . }; 

 class EventJoinWrapper { public: template<class TSome, class ...TParams> inline EventJoinWrapper( IEvent<TParams...>& _event, TSome&& handler ) : m_eventJoin( std::make_shared<HandlerEventJoin<TParams...>>( _event, HandlerCast<TSome>::cast<TParams...>( handler ) ) ) { } constexpr EventJoinWrapper() : m_eventJoin( nullptr ) { } ~EventJoinWrapper() { if( m_eventJoin != nullptr ) delete m_eventJoin; } operator bool() const { return isJoined(); } bool isAssigned() const { return ( m_eventJoin != nullptr ); } bool isJoined() const { return ( m_eventJoin != nullptr && m_eventJoin->isJoined() ); } bool join() { return ( m_eventJoin != nullptr ? m_eventJoin->join() : false ); } bool unjoin() { return ( m_eventJoin != nullptr ? m_eventJoin->unjoin() : false ); } private: AbstractEventJoin* m_eventJoin; }; using EventJoin = EventJoinWrapper; 

рд╣реИрдВрдбрд▓рд░рдХреИрд╕реНрдЯ рд╡рд╣реА рд╕рд╣рд╛рдпрдХ рд╕рдВрд░рдЪрдирд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣рд╛рдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред рд╡реИрд╕реЗ, AbstractEventJoin рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдХреЛ рдЖрднрд╛рд╕реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рддрд╛рдХрд┐ рдЬрдм рдЖрдк EventJoinWrapper рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдореЗрдВ рдЗрд╕рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╣рдЯрд╛ рджреЗрдВ , рддреЛ рд╣реИрдВрдбрд▓рд░рдИрд╡реЗрдВрдЯрдЬреЗрди рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЕрдиреНрдпрдерд╛ THANDlerPtr рдлрд╝реАрд▓реНрдб рдФрд░, рдЗрд╕рд▓рд┐рдП, рд╣реИрдВрдбрд▓рд░ рд╕реНрд╡рдпрдВ рдирд╖реНрдЯ рдирд╣реАрдВ рд╣реЛрдЧрд╛ ред

рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛рдо рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВред EventJoinWrapper рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЙрдкреА рдпрд╛ рдореВрд╡ рдХрд░рдирд╛ рдлрд┐рд░ рд╕реЗ рдЕрдкрдиреЗ рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдореЗрдВ m_eventJoin рдХреЛ рд╣рдЯрд╛ рджреЗрдЧрд╛ ред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЙрджрд╛рд╣рд░рдг рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП std :: shared_ptr рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВAbstractEventJoin , рд╕рд╛рде рд╣реА рд╕рд╛рде рдЖрдВрджреЛрд▓рди (рдФрд░ рдирдХрд▓) рдХреЗ рдереЛрдбрд╝рд╛ рдЕрдиреБрдХреВрд▓рд┐рдд рд╢рдмреНрджрд╛рд░реНрде рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд▓рдЧрд╛рддрд╛рд░ рдСрдкрд░реЗрд╢рди рд╣реЛрдЧрд╛ред

 class EventJoinWrapper { public: EventJoinWrapper( EventJoinWrapper&& other ) : m_eventJoin( std::move( other.m_eventJoin ) ) { } EventJoinWrapper( EventJoinWrapper& other ) : m_eventJoin( other.m_eventJoin ) { } ~EventJoinWrapper() { /*empty*/ } EventJoinWrapper& operator=( EventJoinWrapper&& other ) { m_eventJoin = std::move( other.m_eventJoin ); return *this; } EventJoinWrapper& operator=( const EventJoinWrapper& other ) { m_eventJoin = other.m_eventJoin; return *this; } . . . private: std::shared_ptr<AbstractEventJoin> m_eventJoin; }; 

рдЕрдм рдЬрдм рдХрд┐рд╕реА рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХрд┐рд╕реА рдШрдЯрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рддреБрд░рдВрдд рдПрдХ рдирдП рдХрдиреЗрдХреНрд╢рди рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 template<class ...TParams> class IEvent { . . . public: template<class TSome> EventJoin operator+=( TSome&& some ) { EventJoin result( *this, std::forward<TSome>( some ) ); result.join(); return result; } . . . }; 

рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ razrulivaniya рддреНрд░рд┐рдХреЛрдгреАрдп рдмрд╛рдж include'am (; EventJointWrapper <IEvent <= EventJointWrapper.hpp = HandlerEventJoin.hpp; HandlerEventJoin <= IEvent.hpp) рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдЬ рдФрд░ .hpp рдпрд╣ рдФрд░ рднреА рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдХрдиреЗрдХреНрд╢рди рдЗрдВрд╕реНрдЯреЗрдВрд╕реЗрд╕ рдмрдирд╛рдирд╛ рдЙрдиреНрд╣реАрдВ рдирд┐рдпрдореЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░рдиреЗ рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ:

 struct EventHolder { TEvent<const std::string&> onEvent; }; struct MethodsHolder { void method1( const std::string& ) {} void method2( std::string ) {} void method3( std::string&& ) {} void method4( std::string& ) {} void method5( const int& ) {} }; int main( int argc, char* argv[] ) { EventHolder _eventHolder; MethodsHolder _methodsHolder; EventJoin join1 = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( _methodsHolder, MethodsHolder::method1 ) ); // ok EventJoin join2 = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( _methodsHolder, MethodsHolder::method2 ) ); // ok EventJoin join3 = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( _methodsHolder, MethodsHolder::method3 ) ); // error EventJoin join4 = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( _methodsHolder, MethodsHolder::method4 ) ); // error EventJoin join5 = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( _methodsHolder, MethodsHolder::method5 ) ); // error return 0; } 

рд╕рд╛рде рд╣реА, рдЖрдк рдИрд╡реЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЛ "рд╕рдХреНрд╖рдо" / "рдЕрдХреНрд╖рдо" рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП, рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рдП рдЧрдП рдереЗ):

 struct EventHolder { TEvent<const std::string&, unsigned int> onEvent; }; struct MethodsHolder { void handleEvent( const std::string& text, unsigned int count ) { std::cout << "Text '" << text << "' handled " << count << " times." << std::endl; } }; int main__( int argc, char* argv[] ) { EventHolder _eventHolder; MethodsHolder methodsHolder; EventJoin eventJoin = EventJoin( _eventHolder.onEvent, METHOD_HANDLER( methodsHolder, MethodsHolder::handleEvent ) ); static const std::string handlingText = "testing..."; for( int i = 0; i < 10; ++i ) { if( eventJoin.isJoined() ) eventJoin.unjoin(); else eventJoin.join(); _eventHolder.onEvent( handlingText, i ); } return 0; } 

 Text 'testing...' handled 0 times. Text 'testing...' handled 2 times. Text 'testing...' handled 4 times. Text 'testing...' handled 6 times. Text 'testing...' handled 8 times. 

рдкрд░рд┐рдгрд╛рдо


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдПрдХ рд▓реЗрдЦ рдХреЛ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЙрддрдирд╛ рдХрдо рд▓рд┐рдЦрдиреЗ рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡рд┐рдлрд▓ рд╣реЛрдиреЗ рдХрд╛ рдХрд╛рд░реНрдпред

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдШрдЯрдирд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛рдлреА рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реИ рдФрд░ рдХрдо рд╕реЗ рдХрдо рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред

рдПрдХ рдмрд╣реБрдд рд╣реА рдмреЛрдЭрд┐рд▓ рдЙрджрд╛рд╣рд░рдг рдЬреЛ рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ
 #include <iostream> #include <functional> #include "events/event.hpp" #include "events/handler/methodeventhandler.hpp" #include "events/handler/functoreventhandler.hpp" #include "events/join/handlereventjoin.hpp" #include "events/join/eventjoinwrapper.hpp" class Foo { public: Foo() : onMake( m_onMake ), m_onMake(), m_onMakeInner(), m_makeCount( 0 ) { m_onMakeInner += FUNCTOR_HANDLER( m_onMake ); } IEvent<unsigned int>& onMake; void make() { m_onMakeInner( m_makeCount++ ); } private: TEvent<unsigned int> m_onMake, m_onMakeInner; unsigned int m_makeCount; }; namespace instances { Foo& getFoo() { static Foo _foo; return _foo; } } // instances struct FunctorHandler { void operator()( unsigned int makeCount ); }; void functionHandler( unsigned int makeCount ); class ClassHandler { public: void handle( unsigned int makeCount ); }; namespace instances { FunctorHandler& getFunctorHandler() { static FunctorHandler _functorHandler; return _functorHandler; } std::function<void( unsigned int )>& getStdFunctionHandler() { static std::function<void( unsigned int )> _stdFunctionHandler = []( unsigned int makeCount ) { std::cout << "It's std::function handler" << std::endl; if( makeCount >= 2 ) instances::getFoo().onMake -= STD_FUNCTION_HANDLER( instances::getStdFunctionHandler() ); }; return _stdFunctionHandler; } ClassHandler& getClassHandler() { static ClassHandler _classHandler; return _classHandler; } } // instances void FunctorHandler::operator()( unsigned int makeCount ) { std::cout << "It's functor handler" << std::endl; if( makeCount >= 0 ) instances::getFoo().onMake -= FUNCTOR_HANDLER( instances::getFunctorHandler() ); } void functionHandler( unsigned int makeCount ) { std::cout << "It's function handler" << std::endl; if( makeCount >= 3 ) instances::getFoo().onMake -= FUNCTION_HANDLER( functionHandler ); } void ClassHandler::handle( unsigned int makeCount ) { std::cout << "It's method handler" << std::endl; if( makeCount >= 4 ) instances::getFoo().onMake -= MY_METHOD_HANDLER( ClassHandler::handle ); } int main( int argc, char* argv[] ) { Foo& foo = instances::getFoo(); auto lambdaHandler = []( unsigned int ) { std::cout << "It's lambda handler" << std::endl; }; foo.onMake += FUNCTOR_HANDLER( instances::getFunctorHandler() ); foo.onMake += LAMBDA_HANDLER( lambdaHandler ); EventJoin lambdaJoin = foo.onMake += LAMBDA_HANDLER( ( [ &foo, &lambdaHandler ]( unsigned int makeCount ) { if( makeCount >= 1 ) foo.onMake -= LAMBDA_HANDLER( lambdaHandler ); } ) ); foo.onMake += STD_FUNCTION_HANDLER( instances::getStdFunctionHandler() ); foo.onMake += FUNCTION_HANDLER( functionHandler ); foo.onMake += METHOD_HANDLER( instances::getClassHandler(), ClassHandler::handle ); for( int i = 0; i < 6; ++i ) { std::cout << "Make " << i << " time:" << std::endl; foo.make(); std::cout << std::endl; } lambdaJoin.unjoin(); return 0; } 

рдирд┐рд╖реНрдХрд░реНрд╖:

 Make 0 time: It's functor handler It's lambda handler It's std::function handler It's function handler It's method handler Make 1 time: It's lambda handler It's std::function handler It's function handler It's method handler Make 2 time: It's std::function handler It's function handler It's method handler Make 3 time: It's function handler It's method handler Make 4 time: It's method handler Make 5 time: 


рдпрд╣ рдХрдИ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ:

  • рдпрд╣ рдЕрд▓рдЧ рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдШрдЯрдирд╛ рд╕реНрд╡рдпрдВ рдПрдХ рдлрд╝рдирдХрд╛рд░ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдЕрдиреНрдп рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░ рд╕рдХрддрд╛ рд╣реИ;
  • рдЕрдм рдЖрдк рд╣реИрдВрдбрд▓рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░рдВрддрд░ рддрд░реАрдХреЛрдВ (рд╡рд░реНрдЧ рд╕рджрд╕реНрдп рдХрд╛рд░реНрдпреЛрдВ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ; рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрд╡рд╕рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдореМрдЬреВрджрд╛ рд▓реЛрдЧреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдирдП рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВрдбрд▓рд░ рд▓рд┐рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХреЛрдб рдХреА рдЕрдзрд┐рдХ рджреГрд╢реНрдпрддрд╛ рдФрд░ рдкрдардиреАрдпрддрд╛ рдХреЗ рд▓рд┐рдП рд▓реЗрдЦ рдореЗрдВ рдХреБрдЫ рдмрд┐рдВрджреБ рдЫреЛрдбрд╝реЗ рдЧрдП рд╣реИрдВ:

  • рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ (рд╡рд░реНрдЧ рдХреЗ рд╕рджрд╕реНрдп рд╕рдорд╛рд░реЛрд╣) рдХреЗ рд░рд┐рдЯрд░реНрди рдореВрд▓реНрдп рдХрд╛ рдкреНрд░рдХрд╛рд░ рдХреЛрдИ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд░реВрд░реА рдирд╣реАрдВ рдХрд┐ рд╢реВрдиреНрдп (рд╣реИрдВрдбрд▓рд░-рдлрдВрдХреНрд╢рдирд▓рд░реНрд╕ рдХреЗ рд▓рд┐рдП, рдпрд╣ рднреА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛)
  • рд╕рдВрдкреВрд░реНрдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рд▓рд┐рдП рдирд╛рдорд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВ (рдпрджрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╣рдореЗрд╢рд╛ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ);
  • рдХреБрдЫ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ noexcept рд╕реНрдкреЗрд╕рд┐рдпрд░ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ ред

рдЙрди рд╕рднреА рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрдо рд╕реЗ рдХрдо рддрд┐рд░рдЫреЗ, рдХрдо рдзрдиреБрд╖ рдХреЗ рд╕рд╛рде рдпрд╣рд╛рдВ рдкрдврд╝реЗ рд╣реИрдВред рдореИрдВ рд╕рднреА рдХреЛрдб рд╕рдВрд▓рдЧреНрди рдХрд░рддрд╛ рд╣реВрдВ; рдЗрд╕реЗ рдпрд╣рд╛рдВ (рд╕рднреА рдирд╡реАрдирддрдо рд╕реБрдзрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде) рднреА рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред

рдкреВрд░рд╛ рдХреЛрдб
./events/helpers/is_equatable.hpp
 #pragma once #include <type_traits> template<class T> class is_equatable { private: template<class U> static constexpr std::true_type exists( decltype( std::declval<U>() == std::declval<U>() )* = nullptr ) noexcept; template<class U> static constexpr std::false_type exists( ... ) noexcept; public: static constexpr bool value = decltype( exists<T>( nullptr ) )::value; }; 


./events/handlers/abstracteventhandler.hpp
 #pragma once #include "eventhandlerptr.h" namespace events { namespace handlers { template<class ...TParams> class AbstractEventHandler { using MyType = AbstractEventHandler<TParams...>; public: virtual ~AbstractEventHandler() {} virtual void call( TParams... params ) = 0; bool operator==( const MyType& other ) const noexcept { return isEquals( other ); } bool operator!=( const MyType& other ) const noexcept { return !( *this == other ); } protected: AbstractEventHandler() {} virtual bool isEquals( const MyType& other ) const noexcept = 0; }; } // handlers } // events 


./events/handlers/eventhandlerptr.h
 #pragma once #include <memory> namespace events { namespace handlers { template<class ...TParams> class AbstractEventHandler; template<class ...Types> using TEventHandlerPtr = std::shared_ptr<AbstractEventHandler<Types...>>; } // handlers } // events 


./events/handlers/functoreventhandler.hpp
 #pragma once #include <memory> #include <assert.h> #include "abstracteventhandler.hpp" #include "../helpers/is_equatable.hpp" namespace events { namespace handlers { namespace { template<class TFunctor, class ...TParams> struct IsFunctorParamsCompatible { private: template<class TCheckedFunctor, class ...TCheckedParams> static constexpr std::true_type exists( decltype( std::declval<TCheckedFunctor>()( std::declval<TCheckedParams>()... ) )* = nullptr ) noexcept; template<class TCheckedFunctor, class ...TCheckedParams> static constexpr std::false_type exists( ... ) noexcept; public: static constexpr bool value = decltype( exists<TFunctor, TParams...>( nullptr ) )::value; }; } // template<class TFunctor> class FunctorHolder; template<class TFunctor, class ...TParams> class FunctorEventHandler : public AbstractEventHandler<TParams...> { using MyType = FunctorEventHandler<TFunctor, TParams...>; using TFunctorHolderPtr = std::shared_ptr<FunctorHolder<TFunctor>>; public: FunctorEventHandler( TFunctorHolderPtr functorHolder ) : AbstractEventHandler<TParams...>(), m_functorHolder( functorHolder ) { assert( m_functorHolder != nullptr ); } virtual void call( TParams... params ) override { static_assert( IsFunctorParamsCompatible<TFunctor, TParams...>::value, "Event and functor arguments are not compatible" ); m_functorHolder->m_functor( params... ); } protected: virtual bool isEquals( const AbstractEventHandler<TParams...>& other ) const noexcept override { const MyType* _other = dynamic_cast<const MyType*>( &other ); return ( _other != nullptr && *m_functorHolder == *_other->m_functorHolder ); } private: TFunctorHolderPtr m_functorHolder; }; namespace { template<class TEqu, class TEnabled = void> struct EqualityChecker; template<class TEquatable> struct EqualityChecker<TEquatable, typename std::enable_if<is_equatable<TEquatable>::value>::type> { static constexpr bool isEquals( const TEquatable& operand1, const TEquatable& operand2 ) noexcept { return ( operand1 == operand2 ); } }; template<class TNonEquatable> struct EqualityChecker<TNonEquatable, typename std::enable_if<!is_equatable<TNonEquatable>::value>::type> { static constexpr bool isEquals( const TNonEquatable& operand1, const TNonEquatable& operand2 ) noexcept { return ( &operand1 == &operand2 ); } }; } // template<class TFunctor> class FunctorHolder { using MyType = FunctorHolder<TFunctor>; public: template<class ...TCallParams> operator TEventHandlerPtr<TCallParams...>() { return TEventHandlerPtr<TCallParams...>( new FunctorEventHandler<TFunctor, TCallParams...>( m_me.lock() ) ); } bool operator==( const MyType& other ) const noexcept { return EqualityChecker<TFunctor>::isEquals( m_functor, other.m_functor ); } bool operator!=( const MyType& other ) const noexcept { return !( *this == other ); } template<class TFunctor> static std::shared_ptr<MyType> create( TFunctor&& functor ) { std::shared_ptr<MyType> result( new MyType( functor ) ); result->m_me = result; return result; } private: FunctorHolder( TFunctor& functor ) : m_functor( functor ), m_me() { } TFunctor& m_functor; std::weak_ptr<MyType> m_me; template<class TFunctor, class ...TParams> friend class FunctorEventHandler; }; template<class TFunctor> std::shared_ptr<FunctorHolder<TFunctor>> createFunctorEventHandler( TFunctor&& functor ) { return FunctorHolder<TFunctor>::create( functor ); } } // handlers } // events #define FUNCTOR_HANDLER( Functor ) ::events::handlers::createFunctorEventHandler( Functor ) #define LAMBDA_HANDLER( Lambda ) FUNCTOR_HANDLER( Lambda ) #define STD_FUNCTION_HANDLER( StdFunction ) FUNCTOR_HANDLER( StdFunction ) #define FUNCTION_HANDLER( Function ) FUNCTOR_HANDLER( &Function ) 


./events/handlers/methodeventhandler.hpp
 #pragma once #include <memory> #include <assert.h> #include "abstracteventhandler.hpp" namespace events { namespace handlers { namespace { template<class TMethodHolder, class ...TParams> struct IsMethodParamsCompatible { private: template<class TCheckedMethodHolder, class ...TCheckedParams> static constexpr std::true_type exists( decltype( ( std::declval<TCheckedMethodHolder>().m_object.*std::declval<TCheckedMethodHolder>().m_method )( std::declval<TCheckedParams>()... ) )* = nullptr ) noexcept; template<class TCheckedMethodHolder, class ...TCheckedParams> static constexpr std::false_type exists( ... ) noexcept; public: static constexpr bool value = decltype( exists<TMethodHolder, TParams...>( nullptr ) )::value; }; } // template<class TMethodHolder, class ...TParams> class MethodEventHandler : public AbstractEventHandler<TParams...> { using MyType = MethodEventHandler<TMethodHolder, TParams...>; using TMethodHolderPtr = std::shared_ptr<TMethodHolder>; public: MethodEventHandler( TMethodHolderPtr methodHolder ) : AbstractEventHandler<TParams...>(), m_methodHolder( methodHolder ) { assert( m_methodHolder != nullptr ); } virtual void call( TParams... params ) override { static_assert( IsMethodParamsCompatible<TMethodHolder, TParams...>::value, "Event and method arguments are not compatible" ); ( m_methodHolder->m_object.*m_methodHolder->m_method )( params... ); } protected: virtual bool isEquals( const AbstractEventHandler<TParams...>& other ) const noexcept override { const MyType* _other = dynamic_cast<const MyType*>( &other ); return ( _other != nullptr && *m_methodHolder == *_other->m_methodHolder ); } private: TMethodHolderPtr m_methodHolder; }; template<class TObject, class TResult, class ...TParams> class MethodHolder { using MyType = MethodHolder<TObject, TResult, TParams...>; using TMethod = TResult( TObject::* )( TParams... ); public: template<class ...TCallParams> operator TEventHandlerPtr<TCallParams...>() { return TEventHandlerPtr<TCallParams...>( new MethodEventHandler<MyType, TCallParams...>( m_me.lock() ) ); } bool operator==( const MyType& other ) const noexcept { return ( &m_object == &other.m_object && m_method == other.m_method ); } bool operator!=( const MyType& other ) const noexcept { return !( *this == other ); } template<class TObject, class ...TParams> static std::shared_ptr<MyType> create( TObject& object, TMethod method ) { std::shared_ptr<MyType> result( new MyType( object, method ) ); result->m_me = result; return result; } private: MethodHolder( TObject& object, TMethod method ) : m_object( object ), m_method( method ) { assert( m_method != nullptr ); } TObject& m_object; TMethod m_method; std::weak_ptr<MyType> m_me; template<class TMethodHolder, class ...TParams> friend class MethodEventHandler; template<class TMethodHolder, class ...TParams> friend struct IsMethodParamsCompatible; }; template<class TObject, class TResult, class ...TParams> std::shared_ptr<MethodHolder<TObject, TResult, TParams...>> createMethodEventHandler( TObject& object, TResult( TObject::*method )( TParams... ) ) { return MethodHolder<TObject, TResult, TParams...>::create( object, method ); } } // handlers } // events #define METHOD_HANDLER( Object, Method ) ::events::handlers::createMethodEventHandler( Object, &Method ) #define MY_METHOD_HANDLER( Method ) METHOD_HANDLER( *this, Method ) 


./events/handlers/handlercast.hpp
 #pragma once #include <memory> #include "eventhandlerptr.h" namespace events { namespace handlers { template<class TSome> struct HandlerCast { template<class ...Types> static constexpr TEventHandlerPtr<Types...> cast( TSome& some ) { return static_cast<TEventHandlerPtr<Types...>>( some ); } }; template<class TPtr> struct HandlerCast<std::shared_ptr<TPtr>> { template<class ...Types> static constexpr TEventHandlerPtr<Types...> cast( std::shared_ptr<TPtr> some ) { return HandlerCast<TPtr>::cast<Types...>( *some ); } }; } // handlers } // events 


./events/event.hpp
 #pragma once #include <type_traits> #include <list> #include <memory> #include <shared_mutex> #include <algorithm> #include <assert.h> #include "handlers/abstracteventhandler.hpp" #include "handlers/eventhandlerptr.h" #include "handlers/handlercast.hpp" #include "joins/eventjoinwrapper.hpp" namespace events { namespace joins { template<class ...TParams> class HandlerEventJoin; } template<class ...TParams> class IEvent { public: template<class TSome> EventJoin operator+=( TSome&& some ) { EventJoin result( *this, std::forward<TSome>( some ) ); result.join(); return result; } template<class TSome> bool operator-=( TSome&& some ) { return removeHandler( handlers::HandlerCast<TSome>::cast<TParams...>( some ) ); } protected: using TMyEventHandlerPtr = handlers::TEventHandlerPtr<TParams...>; IEvent() {} virtual bool isHandlerAdded( const TMyEventHandlerPtr& eventHandler ) const = 0; virtual bool addHandler( TMyEventHandlerPtr eventHandler ) = 0; virtual bool removeHandler( TMyEventHandlerPtr eventHandler ) = 0; friend class joins::HandlerEventJoin<TParams...>; }; template<class ...TParams> class TEvent : public IEvent<TParams...> { using TEventHandlerIt = typename std::list<TMyEventHandlerPtr>::const_iterator; public: TEvent() : m_handlers(), m_currentIt(), m_isCurrentItRemoved( false ), m_handlerListMutex() { } void operator()( TParams... params ) { m_handlerListMutex.lock_shared(); m_isCurrentItRemoved = false; m_currentIt = m_handlers.begin(); while( m_currentIt != m_handlers.end() ) { m_handlerListMutex.unlock_shared(); ( *m_currentIt )->call( params... ); m_handlerListMutex.lock_shared(); if( m_isCurrentItRemoved ) { m_isCurrentItRemoved = false; TEventHandlerIt removedIt = m_currentIt; ++m_currentIt; deleteHandler( removedIt ); } else { ++m_currentIt; } } m_handlerListMutex.unlock_shared(); } protected: virtual bool isHandlerAdded( const TMyEventHandlerPtr& eventHandler ) const override { std::shared_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); return ( findEventHandler( eventHandler ) != m_handlers.end() ); } virtual bool addHandler( TMyEventHandlerPtr eventHandler ) override { std::unique_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); if( findEventHandler( eventHandler ) == m_handlers.end() ) { m_handlers.push_back( std::move( eventHandler ) ); return true; } return false; } virtual bool removeHandler( TMyEventHandlerPtr eventHandler ) override { std::unique_lock<std::shared_mutex> _handlerListMutexLock( m_handlerListMutex ); auto it = findEventHandler( eventHandler ); if( it != m_handlers.end() ) { if( it == m_currentIt ) m_isCurrentItRemoved = true; else deleteHandler( it ); return true; } return false; } private: //      'm_handlerListMutex' inline TEventHandlerIt findEventHandler( const TMyEventHandlerPtr& eventHandler ) const noexcept { return std::find_if( m_handlers.cbegin(), m_handlers.cend(), [ &eventHandler ]( const TMyEventHandlerPtr& oneHandler ) { return ( *oneHandler == *eventHandler ); } ); } //      'm_handlerListMutex' inline void deleteHandler( TEventHandlerIt it ) { m_handlers.erase( it ); } std::list<TMyEventHandlerPtr> m_handlers; //    'm_handlerListMutex' mutable TEventHandlerIt m_currentIt; mutable bool m_isCurrentItRemoved; mutable std::shared_mutex m_handlerListMutex; }; } // events 


./events/joins/abstracteventjoin.h
 #pragma once namespace events { namespace joins { class AbstractEventJoin { public: virtual ~AbstractEventJoin(); virtual bool isJoined() const = 0; virtual bool join() = 0; virtual bool unjoin() = 0; protected: AbstractEventJoin(); }; } // joins } // events 


./events/joins/abstracteventjoin.cpp
 #include "abstracteventjoin.h" namespace events { namespace joins { AbstractEventJoin::AbstractEventJoin() { } AbstractEventJoin::~AbstractEventJoin() { } } // joins } // events 


./events/joins/handlereventjoin.h
 #pragma once #include "abstracteventjoin.h" #include "../handlers/eventhandlerptr.h" namespace events { template<class ...TParams> class IEvent; namespace joins { template<class ...TParams> class HandlerEventJoin : public AbstractEventJoin { public: HandlerEventJoin( IEvent<TParams...>& _event, ::events::handlers::TEventHandlerPtr<TParams...> handler ) : AbstractEventJoin(), m_event( _event ), m_handler( handler ) { } virtual inline bool isJoined() const override; virtual inline bool join() override; virtual inline bool unjoin() override; private: IEvent<TParams...>& m_event; ::events::handlers::TEventHandlerPtr<TParams...> m_handler; }; } // joins } // events 


./events/joins/handlereventjoin.hpp
 #pragma once #include "handlereventjoin.h" #include "../event.hpp" namespace events { namespace joins { template<class ...TParams> bool HandlerEventJoin<TParams...>::isJoined() const { return m_event.isHandlerAdded( m_handler ); } template<class ...TParams> bool HandlerEventJoin<TParams...>::join() { return m_event.addHandler( m_handler ); } template<class ...TParams> bool HandlerEventJoin<TParams...>::unjoin() { return m_event.removeHandler( m_handler ); } } // joins } // events 


./events/joins/eventjoinwrapper.h
 #pragma once #include <memory> #include "../handlers/eventhandlerptr.h" namespace events { template<class ...TParams> class IEvent; namespace joins { class AbstractEventJoin; class EventJoinWrapper { public: template<class TSome, class ...TParams> inline EventJoinWrapper( IEvent<TParams...>& _event, TSome&& handler ); constexpr EventJoinWrapper() noexcept; EventJoinWrapper( EventJoinWrapper&& other ) noexcept; EventJoinWrapper( EventJoinWrapper& other ) noexcept; EventJoinWrapper& operator=( EventJoinWrapper&& other ) noexcept; EventJoinWrapper& operator=( const EventJoinWrapper& other ) noexcept; operator bool() const; bool isAssigned() const; bool isJoined() const; bool join(); bool unjoin(); private: std::shared_ptr<AbstractEventJoin> m_eventJoin; }; } // joins using EventJoin = joins::EventJoinWrapper; } // events 


./events/joins/eventjoinwrapper.hpp
 #pragma once #include "eventjoinwrapper.h" #include "handlereventjoin.h" #include "../handlers/handlercast.hpp" namespace events { namespace joins { template<class TSome, class ...TParams> EventJoinWrapper::EventJoinWrapper( IEvent<TParams...>& _event, TSome&& handler ) : m_eventJoin( std::make_shared<HandlerEventJoin<TParams...>>( _event, ::events::handlers::HandlerCast<TSome>::cast<TParams...>( handler ) ) ) { } } // joins } // events 


./events/joins/eventjoinwrapper.cpp
 #include "eventjoinwrapper.h" #include <type_traits> #include "abstracteventjoin.h" namespace events { namespace joins { constexpr EventJoinWrapper::EventJoinWrapper() noexcept : m_eventJoin( nullptr ) { } EventJoinWrapper::EventJoinWrapper( EventJoinWrapper&& other ) noexcept : m_eventJoin( std::move( other.m_eventJoin ) ) { } EventJoinWrapper::EventJoinWrapper( EventJoinWrapper& other ) noexcept : m_eventJoin( other.m_eventJoin ) { } EventJoinWrapper& EventJoinWrapper::operator=( EventJoinWrapper&& other ) noexcept { m_eventJoin = std::move( other.m_eventJoin ); return *this; } EventJoinWrapper& EventJoinWrapper::operator=( const EventJoinWrapper& other ) noexcept { m_eventJoin = other.m_eventJoin; return *this; } EventJoinWrapper::operator bool() const { return isJoined(); } bool EventJoinWrapper::isAssigned() const { return ( m_eventJoin != nullptr ); } bool EventJoinWrapper::isJoined() const { return ( m_eventJoin != nullptr && m_eventJoin->isJoined() ); } bool EventJoinWrapper::join() { return ( m_eventJoin != nullptr ? m_eventJoin->join() : false ); } bool EventJoinWrapper::unjoin() { return ( m_eventJoin != nullptr ? m_eventJoin->unjoin() : false ); } } // joins } // events 



UPD1ред рдпрд╣рд╛рдВ рдФрд░ рдкрд╣рд▓реЗ рд▓реЗрдЦ рдореЗрдВ, VC ++ 14 рдХреЗ рддрд╣рдд рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдХреЛрдб рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рдЕрдиреНрдп рд╕рдВрдХрд▓рдХ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рд▓рд┐рдВрдХ рд╕реЗ рд▓реЗрдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдЬреАрд╕реАрд╕реА рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪреАрдЯрд░ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдзрдиреНрдпрд╡рд╛рдж ред
UPD2ред рдзрдиреНрдпрд╡рд╛рдж lexxmark , рдЬреЛ рджреЗрдЦрд╛ рдПрдХрд╛рдзрд┐рдХ рдШрдЯрдирд╛рдУрдВ рдХреЙрд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдзрд╛рдЧрд╛ рдореЗрдВ рдПрдХ рдЫреЗрджред
рдорд╛рдореВрд▓реА рд╕реБрдзрд╛рд░
 namespace { template<class ...TParams> struct TypeHelper { using TEventHandlerPtr = handlers::TEventHandlerPtr<TParams...>; using TEventHandlerIt = typename std::list<TEventHandlerPtr>::const_iterator; }; } // template<class ...TParams> class IEvent { . . . protected: using TMyEventHandlerPtr = typename TypeHelper<TParams...>::TEventHandlerPtr; . . . }; namespace { template<class ...TParams> struct EventCore { using TMyHandlerPtr = typename TypeHelper<TParams...>::TEventHandlerPtr; std::list<TMyHandlerPtr> handlers; mutable std::shared_mutex coreMutex; }; template<class ...TParams> class HandlerRunner { using TMyEventCore = EventCore<TParams...>; using TMyHandlerIt = typename TypeHelper<TParams...>::TEventHandlerIt; public: HandlerRunner( TMyEventCore& eventCore ) : m_eventCore( eventCore ), currentIt(), wasRemoving( false ) { } void run( TParams... params ) { m_eventCore.coreMutex.lock_shared(); currentIt = m_eventCore.handlers.begin(); wasRemoving = false; while( currentIt != m_eventCore.handlers.end() ) { m_eventCore.coreMutex.unlock_shared(); ( *currentIt )->call( params... ); m_eventCore.coreMutex.lock_shared(); if( wasRemoving ) wasRemoving = false; else ++currentIt; } m_eventCore.coreMutex.unlock_shared(); } TMyHandlerIt currentIt; mutable bool wasRemoving; private: TMyEventCore& m_eventCore; }; } // template<class ...TParams> class TEvent : public IEvent<TParams...> { using TMyEventHandlerPtr = typename TypeHelper<TParams...>::TEventHandlerPtr; using TMyEventHandlerIt = typename TypeHelper<TParams...>::TEventHandlerIt; using TMyHandlerRunner = HandlerRunner<TParams...>; public: TEvent() : m_core() { } void operator()( TParams... params ) { TMyHandlerRunner newHandlerRunner( m_core ); m_core.coreMutex.lock_shared(); auto it = m_handlerRunners.insert( m_handlerRunners.end(), &newHandlerRunner ); m_core.coreMutex.unlock_shared(); newHandlerRunner.run( params... ); m_core.coreMutex.lock_shared(); m_handlerRunners.erase( it ); m_core.coreMutex.unlock_shared(); } protected: virtual bool isHandlerAdded( const TMyEventHandlerPtr& eventHandler ) const override { std::shared_lock<std::shared_mutex> _coreMutexLock( m_core.coreMutex ); return ( findEventHandler( eventHandler ) != m_core.handlers.end() ); } virtual bool addHandler( TMyEventHandlerPtr eventHandler ) override { std::unique_lock<std::shared_mutex> _coreMutexLock( m_core.coreMutex ); if( findEventHandler( eventHandler ) == m_core.handlers.end() ) { m_core.handlers.push_back( std::move( eventHandler ) ); return true; } return false; } virtual bool removeHandler( TMyEventHandlerPtr eventHandler ) override { std::unique_lock<std::shared_mutex> _coreMutexLock( m_core.coreMutex ); auto it = findEventHandler( eventHandler ); if( it != m_core.handlers.end() ) { for( TMyHandlerRunner* oneHandlerRunner : m_handlerRunners ) { if( it == oneHandlerRunner->currentIt ) { ++oneHandlerRunner->currentIt; oneHandlerRunner->wasRemoving = true; } } m_core.handlers.erase( it ); return true; } return false; } private: //      'm_core.coreMutex' inline TMyEventHandlerIt findEventHandler( const TMyEventHandlerPtr& eventHandler ) const { return std::find_if( m_core.handlers.cbegin(), m_core.handlers.cend(), [ &eventHandler ]( const TMyEventHandlerPtr& oneHandler ) { return ( *oneHandler == *eventHandler ); } ); } EventCore<TParams...> m_core; std::list<TMyHandlerRunner*> m_handlerRunners; }; 

(, , ) HandlerRunner , . , : currentIt ( ) wasRemoving (, ). HandlerRunner' operator() ; (, ) , EventCore . рдЗрд╕ рдкреНрд░рдХрд╛рд░ , , , , , .
UPD3ред Isnullxbh рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж , рдПрдХ рдФрд░ рддреНрд░реБрдЯрд┐ рдкрд╛рдИ рдЧрдИред рдпрд╣ рдЕрдиреБрдЪрд┐рдд рднрдВрдбрд╛рд░рдг рдФрд░ рдмрд╛рдж рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рдкрд╣реБрдБрдЪ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ рдЬреЛ рдХрд┐ рдкреНрд░рддрд┐рджреНрд╡рдВрджреНрд╡рд┐рддрд╛ (рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рд▓рдВрдмреЛрджрд░ рднрд╛рд╡) рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ ред
рд╕реБрдзрд╛рд░
, lvalue , lvalue -, , rvalue , (, ). :
 template<class TSome> struct ObjectSaver; template<class LValue> struct ObjectSaver<LValue&> { using TObject = LValue&; }; template<class RValue> struct ObjectSaver<RValue&&> { using TObject = RValue; }; 

Holder ( lvalue rvalue ), , ┬л┬╗ . type erasing ( ). , Holder' .
 template<class TBase> struct AbstractInnerHolder { virtual ~AbstractInnerHolder() {} virtual inline TBase& get() = 0; inline const TBase& get() const { return const_cast<AbstractInnerHolder<TBase>&>( *this ).get(); } }; template<class TBase, class TInner> struct TInnerHolder : public AbstractInnerHolder<TBase> { using TInnerObject = typename ObjectSaver<TInner>::TObject; TInnerHolder( TInner _inner ) : AbstractInnerHolder<TBase>(), inner( std::forward<TInner>( _inner ) ) { } virtual inline TBase& get() override { return static_cast<TBase&>( inner ); } TInnerObject inner; }; template<class TAssignBase, class TArgInner> AbstractInnerHolder<TAssignBase>& createInnerHolder( TArgInner&& inner ) { using TAssignInner = decltype( inner ); return *new TInnerHolder<TAssignBase, TAssignInner>( std::forward<TArgInner>( inner ) ); } 

Holder' . MethodHolder' .
 template<class TObject, class TResult, class ...TParams> class MethodHolder { . . . using MyType = MethodHolder<TObject, TResult, TParams...>; using TMethod = TResult( TObject::* )( TParams... ); public: ~MethodHolder() { delete &m_innerHolder; } bool operator==( const MyType& other ) const { return ( &m_innerHolder.get() == &other.m_innerHolder.get() && m_method == other.m_method ); } template<class TArgObject> static std::shared_ptr<MyType> create( TArgObject&& object, TMethod method ) { std::shared_ptr<MyType> result( new MyType( std::forward<TArgObject>( object ), method ) ); result->m_me = result; return result; } private: template<class TArgObject> MethodHolder( TArgObject&& object, TMethod method ) : m_innerHolder( createInnerHolder<TObject>( std::forward<TArgObject>( object ) ) ), m_method( method ) { assert( m_method != nullptr ); } AbstractInnerHolder<TObject>& m_innerHolder; TMethod m_method; std::weak_ptr<MyType> m_me; . . . }; 

 namespace { template<class TMethodHolder, class ...TParams> struct IsMethodParamsCompatible { private: template<class TCheckedMethodHolder, class ...TCheckedParams> static constexpr std::true_type exists( decltype( ( std::declval<TCheckedMethodHolder>().m_innerHolder.get().*std::declval<TCheckedMethodHolder>().m_method )( std::declval<TCheckedParams>()... ) )* = nullptr ); . . . }; } // template<class TMethodHolder, class ...TParams> class MethodEventHandler : public AbstractEventHandler<TParams...> { public: virtual void call( TParams... params ) override { static_assert( IsMethodParamsCompatible<TMethodHolder, TParams...>::value, "Event and method arguments are not compatible" ); ( m_methodHolder->m_innerHolder.get().*m_methodHolder->m_method )( params... ); } private: TMethodHolderPtr m_methodHolder; . . . }; 

 template<class TObject, class TResult, class ...TParams> std::shared_ptr<MethodHolder<typename std::decay<TObject>::type, TResult, TParams...>> createMethodEventHandler( TObject&& object, TResult( std::decay<TObject>::type::*method )( TParams... ) ) { return MethodHolder<std::decay<TObject>::type, TResult, TParams...>::create( std::forward<TObject>( object ), method ); } 

рд╣реЛ рдЧрдпрд╛ред FunctorHolder . . - .

рдкреБрдирд╢реНрдЪ рдХреНрдпреВрдЯреА рд╕рдВрдХреЗрдд / рд╕реНрд▓реЙрдЯ рддрдВрддреНрд░ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЧрд▓рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдореИрдВ рдХрд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпреВ ++ рд╕реА рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд╛рдорд╛рдиреНрдп рдврд╛рдВрдЪрд╛ рд╣реИ ред рдЕрдиреНрдп рдмрд╛рддреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕рдХрд╛ рдЕрдкрдирд╛ рдИрд╡реЗрдВрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рддрдВрддреНрд░ рднреА рд╣реИ , рдЬрд┐рд╕рдореЗрдВ рдИрд╡реЗрдВрдЯ рдХреЗ рдПрдирд╛рд▓реЙрдЧреНрд╕ рдФрд░ рд╕реНрд▓реЙрдЯреНрд╕ рдХреЗ рдПрдирд╛рд▓реЙрдЧреНрд╕ рдХреЗ рдПрдирд╛рд▓реЙрдЧреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд┐рдЧреНрдирд▓ рд╣реЛрддреЗ рд╣реИрдВред рдпрд╣ рдореЗрдЯрд╛-рдСрдмреНрдЬреЗрдХреНрдЯ рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЕрдзрд┐рдХ рд╡реИрд╢реНрд╡рд┐рдХ рдореЗрдЯрд╛-рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ , рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ, рдХреНрдпреВрдЯреА рд╕реЗ рдЕрдзрд┐рдХ C ++ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдРрдб-рдСрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред

рджреЛрдиреЛрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ:


  • рд╕рд┐рдЧреНрдирд▓ (рдШрдЯрдирд╛рдУрдВ) рдХреЛ рд╡рд┐рдзрд┐рдпреЛрдВ (рд╕рджрд╕реНрдп рдХрд╛рд░реНрдпреЛрдВ), рдлрдВрдХреНрд╢рдирд▓рд░реНрд╕ рдФрд░ рдлрд╝рдВрдХреНрд╢рдВрд╕ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреА рдХреНрд╖рдорддрд╛;
  • () (), ( lvalue , rvalue );
  • ( );
  • () ( ).

Qt :



Qt :


  • QObject ;
    , , QObject , , , ( : Virtual inheritance with QObject is not supported. ); , , ;
  • template';
    , public - QObject ; moc' ; ,
    ,
     #include <QObject> class AbstractProperty : public QObject { Q_OBJECT protected: AbstractProperty(); signals: void valueChanged(); }; template<class TSource> class TProperty : public AbstractProperty { public: TProperty( const TSource& value = TSource() ) : AbstractProperty(), m_value( value ) { } const TSource& value() const { return m_value; } void setValue( const TSource& newValue ) { if( newValue != m_value ) { m_value = newValue; emit valueChanged(); } } private: TSource m_value; }; 

    , valueChanged ( , ) , .
    , , ;
  • .cpp-;
    ;
  • QMetaObject::Connection ;
    , Qt ( ) , ; () , , ; , ; Qt ;
  • рдПрдордУрд╕реА рджреНрд╡рд╛рд░рд╛ рдЕрддрд┐рд░рд┐рдХреНрдд рдЙрддреНрдкрдиреНрди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ ;
    рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдирд┐рд░реНрдгрдп рд╣реИ, рдЬрд╣рд╛рдВ рд╕рдВрдХреЗрддреЛрдВ рдФрд░ рд╕реНрд▓реЙрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП (рд╕реНрд▓реЙрдЯ рд╣рдореЗрд╢рд╛ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ) рдХрдИ (рдкреНрд░рддреНрдпреЗрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ рджреНрд╡рд╛рд░рд╛) рдЙрддреНрдкрдиреНрди рдлрд╛рдЗрд▓реЗрдВ рд╣реЛрддреА рд╣реИрдВ рдЬреЛ рдХреБрдЫ рдЕрд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рдХрд╛рд░рдг рдмрдирддреА рд╣реИрдВ; рд▓реЗрдХрд┐рди рдИрдорд╛рдирджрд╛рд░ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╕рдмрд╕реЗ рдорд╛рдореВрд▓реА рджреЛрд╖ рд╣реИред

рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдХреНрдпреВрдЯреА рдХреЗ рд╕рд╛рде рдпрд╣ рддреБрд▓рдирд╛ рдЕрднреА рднреА рдмрд╣реБрдд рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рд╣реИ рдФрд░ рдЗрд╕ рдврд╛рдВрдЪреЗ рдХреЛ рдЙрднрд╛рд░рдиреЗ рдпрд╛ рдирд┐рдВрджрд╛ рдХрд░рдиреЗ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╕рдВрдХреЗрдд / рд╕реНрд▓реЙрдЯ рддрдВрддреНрд░ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреНрдпреВрдЯреА рдорд╣рд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рджреЛрдиреЛрдВ рдЗрд╕ рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдирд╣реАрдВред рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рд╣рдореЗрд╢рд╛ рддрдп рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХреНрдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдирд╣реАрдВред

Source: https://habr.com/ru/post/hi424593/


All Articles