From 0ce9e7a90366ef1b9545f0df35e29ba3d26fb2ee Mon Sep 17 00:00:00 2001 From: insleker Date: Wed, 24 Apr 2024 11:34:01 +0800 Subject: [PATCH] feat: combine map implement function and virtual override method. --- include/event_transformer.h | 99 +++++++++++++++++++++++++++++++++---- tests/test_event_basic.cpp | 91 +++++++++------------------------- 2 files changed, 113 insertions(+), 77 deletions(-) diff --git a/include/event_transformer.h b/include/event_transformer.h index 88c8b46..df7ae40 100644 --- a/include/event_transformer.h +++ b/include/event_transformer.h @@ -1,21 +1,99 @@ #pragma once -using namespace std; - -template -class EventList; - -template<> -class EventList<> -{}; +#include +#include +#include +#include +#include /** + * @details + * variadic template + template specialization + */ +template +class EventList +{ + // no function here will be expose to outer. + // void hello() + // { + // printf("hello"); + // } +}; + +/** + * base of EventList + */ +template<> +class EventList<> +{ +public: + // template + // void dispatch(EVT evt) + // { + // using namespace std; + // // static_cast*>(evt_li_ptr)->dispatch(evt); + // // for (auto const& [key, val] : fmap) { + // // } + // auto any_func = this->fmap.at(std::type_index(typeid(EVT))); + // if (any_func.has_value()) { + // auto func = std::any_cast>(any_func); + // func(evt); // dispatch + // return; + // } + // // else, call its own private dispatch function. + // // dynamic_cast*>(this)->dispatch(evt); // error: 'EventList<>' is not polymorphic, so I need to + // // create seperate func. + // }; + + template + friend void dispatch(EvntLists* evnt_list_ptr, EVT evt); + + /** + * @todo create templated setting functor meta function. + */ + template + friend void set_meta(EvntLists* evnt_list_ptr, EVT evt); + +protected: + // std::optional + std::map fmap; +}; + +// class Dispatcher +// { +// Dispatcher(Event) +// }; +template +void +dispatch(EvntLists* evnt_list_ptr, EVT evt) +{ + auto base = static_cast*>(evnt_list_ptr); //->dispatch(evt); + auto any_func = base->fmap.at(std::type_index(typeid(EVT))); + if (any_func.has_value()) { + auto func = std::any_cast>(any_func); + func(evt); // dispatch + return; + } + // else, call its own private dispatch function. + dynamic_cast*>(evnt_list_ptr)->dispatch(evt); // error: 'EventList<>' is not polymorphic, so I need to + // create seperate func. +} + +/** + * The second event list, connect between event and base * @todo addition type but without trigger ambiguous error. */ template class EventList : public virtual EventList<> { public: + EventList() + { + // printf("constructor called\n"); + fmap.insert(std::pair(std::type_index(typeid(Event)), std::any())); + // auto any_func = fmap.at(std::type_index(typeid(Event))); + // printf("any val:%d\n", any_func.has_value()); + } virtual void dispatch(const Event&){}; //=0 // virtual void dispatch(Event&) // { @@ -27,8 +105,11 @@ public: // }; }; +/** + * intermediate, and hierachy + */ template class EventList : public EventList , public EventList -{}; \ No newline at end of file +{}; diff --git a/tests/test_event_basic.cpp b/tests/test_event_basic.cpp index a21f174..2fa89ef 100644 --- a/tests/test_event_basic.cpp +++ b/tests/test_event_basic.cpp @@ -57,6 +57,9 @@ class Foo_pp : public Foo public: // for c++ 17 + /** + * if cast back to Foo, template function will disapear. + */ template void dispatch(EVT evt) { @@ -101,61 +104,8 @@ TEST_F(Evt_trans_test, create_test) * I want this be interface only. * @todo require a dynamic map to map from rtti typeinfo to coresponding function。 */ -class Fake_module_process_ev : public EventList -{ - // struct Concept - // { // (5) - // virtual ~Concept() - // { - // } - // virtual void dispatch() = 0; - // }; - - // std::unique_ptr pimpl_; - - // template // (6) - // struct Model : Concept - // { - // Model(const T& t) - // : object(t) - // { - // } - // void dispatch() override - // { - // return object.dispatch(); - // } - - // private: - // T object; - // }; - - -public: - // /** - // * @todo type erase - // * @see https://www.hmoonotes.org/2023/06/cpp-type-erasure.html - // * @see https://www.modernescpp.com/index.php/type-erasure/ - // */ - // // template - // // void dispatch(EVT evt) - // // { - // // // I want to override this. (type erase) - // // std::cout << "base interface\n"; - // // }; - template - void dispatch(EVT evt) - { - using namespace std; - // for (auto const& [key, val] : fmap) { - // } - auto func = std::any_cast>(fmap.at(type_index(typeid(EVT)))); - func(evt); // dispatch - }; - -protected: - // void (*)(std::any &); - std::map fmap; -}; // Fake_module_process_ev +class Fake_module_process_ev : virtual public EventList +{}; // Fake_module_process_ev /** * 用friend 會變成 `dispatch(foo, a_event);` 而非 `foo.dispatch(a_event);` @@ -168,6 +118,8 @@ protected: // template class So5_fake_module_process_ev : virtual public Fake_module_process_ev { + using EventList::dispatch; // to disable warning + so_5::mbox_t target; public: @@ -177,23 +129,21 @@ public: using namespace std; // iterate over all the inherit class and generate function from functor. // - std::function func = [this](AEvent& evt) -> void { so_5::send(target); }; + std::function func = [this](AEvent& evt) -> void { + // so_5::send(target, evt.speed); //both work, but this isn't + so_5::send(target, evt); + }; fmap[type_index(typeid(AEvent))] = std::any(func); // Functor<>; } - // template - // void dispatch(EVT evt) - // { - // // cout << "this is additional wrapper from event name: " << evt.name << "\n"; - // cout << "this is additional wrapper from event name: " - // << "\n"; - // // static_cast&>(*this).dispatch(evt); - // so_5::send(target); - // } + void dispatch(const BEvent& evt) override + { + std::cout << "So5_fake is handling BEvent" << endl; + } }; /** - * simulate module process which require event interface + * simulate module process which require event interface but hide implement. */ void fake_module_process(Fake_module_process_ev* evt_li_ptr) @@ -202,8 +152,13 @@ fake_module_process(Fake_module_process_ev* evt_li_ptr) std::cout << "fake module called\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); const AEvent a_ev = AEvent{ .speed = 5.0 }; - evt_li_ptr->dispatch(a_ev); + // static_cast*>(evt_li_ptr)->dispatch(a_ev); + // static_cast*>(evt_li_ptr)->dispatch(a_ev); + // evt_li_ptr->ev_dispatch(a_ev); // static_cast&>(*evt_li_ptr).dispatch(a_ev); + dispatch(evt_li_ptr, a_ev); + const BEvent b_ev = BEvent(); + dispatch(evt_li_ptr, b_ev); std::cout << "fake module exist\n"; // } @@ -213,7 +168,7 @@ class pinger final : public so_5::agent_t void on_pong(mhood_t cmd) { - std::cout << "actor pinger: received a A event\n"; + std::cout << "actor pinger: received a A event, speed: " << cmd->speed << ".\n"; } public: