#include <functional>
#include <iostream>
#include <map>
#include <memory>
enum class EventType {
SOME_EVENT = 0,
};
class Event {
public:
virtual ~Event() {}
virtual EventType get_event_type() = 0;
};
class SomeEvent: public Event {
public:
SomeEvent(): m_event_type(EventType::SOME_EVENT) {}
void bar() { std::cout << "hello" << std::endl; }
EventType get_event_type() { return this->m_event_type; }
public:
EventType m_event_type;
};
typedef std::function<void(std::unique_ptr<Event>)> EventHandler;
std::map<EventType, EventHandler> event_handlers;
template <class T>
void add_event_handler(EventType event_type, const std::function<void(std::unique_ptr<T>)> &event_handler) {
event_handlers[event_type] = event_handler;
}
void insert_event(std::unique_ptr<Event> event) {
event_handlers[event->get_event_type()](std::move(event));
}
int main(int argc, char **argv) {
add_event_handler<SomeEvent>(EventType::SOME_EVENT, [](auto b) { b->bar(); });
// later...
insert_event(std::make_unique<SomeEvent>());
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPG1hcD4KI2luY2x1ZGUgPG1lbW9yeT4KCmVudW0gY2xhc3MgRXZlbnRUeXBlIHsKICBTT01FX0VWRU5UID0gMCwKfTsKCmNsYXNzIEV2ZW50IHsKcHVibGljOgogIHZpcnR1YWwgfkV2ZW50KCkge30KICB2aXJ0dWFsIEV2ZW50VHlwZSBnZXRfZXZlbnRfdHlwZSgpID0gMDsKfTsKCmNsYXNzIFNvbWVFdmVudDogcHVibGljIEV2ZW50IHsKcHVibGljOgogIFNvbWVFdmVudCgpOiBtX2V2ZW50X3R5cGUoRXZlbnRUeXBlOjpTT01FX0VWRU5UKSB7fQogIHZvaWQgYmFyKCkgeyBzdGQ6OmNvdXQgPDwgImhlbGxvIiA8PCBzdGQ6OmVuZGw7IH0KICBFdmVudFR5cGUgZ2V0X2V2ZW50X3R5cGUoKSB7IHJldHVybiB0aGlzLT5tX2V2ZW50X3R5cGU7IH0KCnB1YmxpYzoKICBFdmVudFR5cGUgbV9ldmVudF90eXBlOwp9OwoKCnR5cGVkZWYgc3RkOjpmdW5jdGlvbjx2b2lkKHN0ZDo6dW5pcXVlX3B0cjxFdmVudD4pPiBFdmVudEhhbmRsZXI7CgpzdGQ6Om1hcDxFdmVudFR5cGUsIEV2ZW50SGFuZGxlcj4gZXZlbnRfaGFuZGxlcnM7Cgp0ZW1wbGF0ZSA8Y2xhc3MgVD4Kdm9pZCBhZGRfZXZlbnRfaGFuZGxlcihFdmVudFR5cGUgZXZlbnRfdHlwZSwgY29uc3Qgc3RkOjpmdW5jdGlvbjx2b2lkKHN0ZDo6dW5pcXVlX3B0cjxUPik+ICZldmVudF9oYW5kbGVyKSB7CiAgZXZlbnRfaGFuZGxlcnNbZXZlbnRfdHlwZV0gPSBldmVudF9oYW5kbGVyOwp9Cgp2b2lkIGluc2VydF9ldmVudChzdGQ6OnVuaXF1ZV9wdHI8RXZlbnQ+IGV2ZW50KSB7CiAgZXZlbnRfaGFuZGxlcnNbZXZlbnQtPmdldF9ldmVudF90eXBlKCldKHN0ZDo6bW92ZShldmVudCkpOwp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpIHsKICBhZGRfZXZlbnRfaGFuZGxlcjxTb21lRXZlbnQ+KEV2ZW50VHlwZTo6U09NRV9FVkVOVCwgW10oYXV0byBiKSB7IGItPmJhcigpOyB9KTsKICAvLyBsYXRlci4uLgogIGluc2VydF9ldmVudChzdGQ6Om1ha2VfdW5pcXVlPFNvbWVFdmVudD4oKSk7Cn0K
prog.cpp: In instantiation of ‘void add_event_handler(EventType, const std::function<void(std::unique_ptr<_Tp>)>&) [with T = SomeEvent]’:
prog.cpp:41:79: required from here
prog.cpp:33:30: error: no match for ‘operator=’ (operand types are ‘std::map<EventType, std::function<void(std::unique_ptr<Event>)> >::mapped_type’ {aka ‘std::function<void(std::unique_ptr<Event>)>’} and ‘const std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>’)
event_handlers[event_type] = event_handler;
In file included from /usr/include/c++/8/functional:59,
from prog.cpp:1:
/usr/include/c++/8/bits/std_function.h:461:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {std::unique_ptr<Event, std::default_delete<Event> >}]’
operator=(const function& __x)
^~~~~~~~
/usr/include/c++/8/bits/std_function.h:461:7: note: no known conversion for argument 1 from ‘const std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>’ to ‘const std::function<void(std::unique_ptr<Event>)>&’
/usr/include/c++/8/bits/std_function.h:479:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {std::unique_ptr<Event, std::default_delete<Event> >}]’
operator=(function&& __x) noexcept
^~~~~~~~
/usr/include/c++/8/bits/std_function.h:479:7: note: no known conversion for argument 1 from ‘const std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>’ to ‘std::function<void(std::unique_ptr<Event>)>&&’
/usr/include/c++/8/bits/std_function.h:493:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::nullptr_t) [with _Res = void; _ArgTypes = {std::unique_ptr<Event, std::default_delete<Event> >}; std::nullptr_t = std::nullptr_t]’
operator=(nullptr_t) noexcept
^~~~~~~~
/usr/include/c++/8/bits/std_function.h:493:7: note: no known conversion for argument 1 from ‘const std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>’ to ‘std::nullptr_t’
/usr/include/c++/8/bits/std_function.h:522:2: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<typename std::decay<_U1>::type>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = _Functor; _Res = void; _ArgTypes = {std::unique_ptr<Event, std::default_delete<Event> >}]’
operator=(_Functor&& __f)
^~~~~~~~
/usr/include/c++/8/bits/std_function.h:522:2: note: template argument deduction/substitution failed:
/usr/include/c++/8/bits/std_function.h: In substitution of ‘template<class _Functor> std::function<void(std::unique_ptr<Event>)>::_Requires<std::function<void(std::unique_ptr<Event>)>::_Callable<typename std::decay<_Tp>::type, typename std::result_of<typename std::decay<_Tp>::type&(std::unique_ptr<Event>)>::type>, std::function<void(std::unique_ptr<Event>)>&> std::function<void(std::unique_ptr<Event>)>::operator=<_Functor>(_Functor&&) [with _Functor = const std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>&]’:
prog.cpp:33:30: required from ‘void add_event_handler(EventType, const std::function<void(std::unique_ptr<_Tp>)>&) [with T = SomeEvent]’
prog.cpp:41:79: required from here
/usr/include/c++/8/bits/std_function.h:522:2: error: no type named ‘type’ in ‘class std::result_of<std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>&(std::unique_ptr<Event>)>’
prog.cpp: In instantiation of ‘void add_event_handler(EventType, const std::function<void(std::unique_ptr<_Tp>)>&) [with T = SomeEvent]’:
prog.cpp:41:79: required from here
/usr/include/c++/8/bits/std_function.h:531:2: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::reference_wrapper<_Functor>) [with _Functor = _Functor; _Res = void; _ArgTypes = {std::unique_ptr<Event, std::default_delete<Event> >}]’
operator=(reference_wrapper<_Functor> __f) noexcept
^~~~~~~~
/usr/include/c++/8/bits/std_function.h:531:2: note: template argument deduction/substitution failed:
prog.cpp:33:30: note: ‘std::function<void(std::unique_ptr<SomeEvent, std::default_delete<SomeEvent> >)>’ is not derived from ‘std::reference_wrapper<_Tp>’
event_handlers[event_type] = event_handler;