#include #include #include #include #include #include #include #include //***************************************************************************** // EventSource mixin //***************************************************************************** // event source traits base template struct Events; // event source mixin (using CRTP) template class EventSource { public: typedef ::Events Events; private: typedef typename Events::EventTable EventTable; // helper type generator template struct GetType { // boost::optional type typedef typename boost::fusion::result_of:: value_at_key::type SignalWrapper; // boost::signal type for particular boost::optional type typedef typename SignalWrapper::value_type Signal; // slot return type for particular boost::signal type typedef typename Signal::result_type SignalReturnType; }; public: // connect event handler template void Connect(Handler&& handler) { GetSignal()->connect(std::move(handler)); } protected: // generate nullary signal template typename GetType::SignalReturnType FireEvent() { return GetSignal()->operator()(); } // generate unary signal template typename GetType::SignalReturnType FireEvent(Arg1 arg1) { return GetSignal()->operator()(arg1); } // ... more overloads (MSVC does not support variadic templates) private: // creates signal if not exists, returns reference to it template typename GetType::SignalWrapper& GetSignal() { auto& signal = boost::fusion::at_key(signals_); if (!signal) signal = boost::in_place(); return signal; } EventTable signals_; }; //***************************************************************************** // Concrete EventSource example //***************************************************************************** // concrete event source traits specialization template<> struct Events { struct Show; struct Close; typedef boost::fusion::map< boost::fusion::pair>>, boost::fusion::pair>> > EventTable; }; // concrete event source class ConcreteEventSource: public EventSource { public: // event emitters void Show() { std::cout << "Show signal generated." << std::endl; FireEvent(); } int Close() { int foo = 3; std::cout << "Close signal generated. foo = " << foo << std::endl; int bar = *FireEvent(foo); std::cout << "Close signal processed. bar = " << bar << std::endl; return bar; } }; //***************************************************************************** // Event listener //***************************************************************************** class EventListener { public: // event handlers void OnShow() { std::cout << "OnShow handler called." << std::endl; } int OnClose(int foo) { std::cout << "OnClose handler called. foo = " << foo << std::endl; return foo * 2; } }; //***************************************************************************** // main //***************************************************************************** int main() { ConcreteEventSource event_source; EventListener event_listener; // connect event handlers event_source.Connect([&](){ event_listener.OnShow(); }); event_source.Connect([&](int foo){ return event_listener.OnClose(foo); }); // fire events event_source.Show(); event_source.Close(); }