#pragma once #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 friend void dispatch(EvntLists* evnt_list_ptr, EVT evt); /** * @todo create templated setting functor meta function. */ template class FunctorT, typename EVT> friend void set_meta(EvntLists* evnt_list_ptr); // 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. } template class FunctorT, typename EVT> void set_meta(EvntLists* evnt_list_ptr) { printf("set meta called\n"); auto base = static_cast*>(evnt_list_ptr); base->fmap.at(std::type_index(typeid(EVT))) = FunctorT(); } /** * 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("normal 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&) // { // cout << "default cb\n"; // }; // virtual void dispatch(const Event) // { // cout << "default cb\n"; // }; }; /** * intermediate, and hierachy */ template class EventList : public EventList , public EventList { // EventList() // { // printf("intermediate constructor called\n"); // } }; /************************************************/ template class FunctorT, class Event> class EventList, Event> : public virtual EventList<> { public: EventList, Event>() { printf("constructor with functor\n"); set_meta, Event>, FunctorT, Event>(this); } }; template class FunctorT, class Event, class... Others> class EventList, Event, Others...> : public EventList, Event> , public EventList { public: EventList, Event, Others...>() { printf("outer, constructor with functor\n"); } };