#include <memory>
#include <functional>
#include <iostream>
struct function_wrapper
{
virtual ~function_wrapper() {}
};
template <typename... Args>
struct variadic_function : function_wrapper
{
variadic_function(std::function<void(Args...)> f) : f_(std::move(f)) {}
void operator()(Args &&... args) { f_(std::forward<Args>(args)...); }
private:
std::function<void(Args...)> f_;
};
class dispatcher
{
public:
template <typename... Args>
void register_event(std::function<void(Args...)> f)
{
f_ = std::make_shared<variadic_function<Args...>>(std::move(f));
}
template <typename... Args>
void post(Args &&... args)
{
auto f = std::dynamic_pointer_cast<variadic_function<Args...>>(f_);
if (f)
{
(*f)(std::forward<Args>(args)...);
}
}
private:
std::shared_ptr<function_wrapper> f_;
};
int main()
{
dispatcher d;
std::function<void(int)> f = [](int a) { std::cout << a << "\n"; };
d.register_event(f);
d.post(42);
return 0;
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnN0cnVjdCBmdW5jdGlvbl93cmFwcGVyCnsKICB2aXJ0dWFsIH5mdW5jdGlvbl93cmFwcGVyKCkge30KfTsKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCB2YXJpYWRpY19mdW5jdGlvbiA6IGZ1bmN0aW9uX3dyYXBwZXIKewogIHZhcmlhZGljX2Z1bmN0aW9uKHN0ZDo6ZnVuY3Rpb248dm9pZChBcmdzLi4uKT4gZikgOiBmXyhzdGQ6Om1vdmUoZikpIHt9CiAgdm9pZCBvcGVyYXRvcigpKEFyZ3MgJiYuLi4gYXJncykgeyBmXyhzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOyB9Cgpwcml2YXRlOgogIHN0ZDo6ZnVuY3Rpb248dm9pZChBcmdzLi4uKT4gZl87Cn07CgpjbGFzcyBkaXNwYXRjaGVyCnsKcHVibGljOgogIHRlbXBsYXRlIDx0eXBlbmFtZS4uLiBBcmdzPgogIHZvaWQgcmVnaXN0ZXJfZXZlbnQoc3RkOjpmdW5jdGlvbjx2b2lkKEFyZ3MuLi4pPiBmKQogIHsKICAgIGZfID0gc3RkOjptYWtlX3NoYXJlZDx2YXJpYWRpY19mdW5jdGlvbjxBcmdzLi4uPj4oc3RkOjptb3ZlKGYpKTsKICB9CgogIHRlbXBsYXRlIDx0eXBlbmFtZS4uLiBBcmdzPgogIHZvaWQgcG9zdChBcmdzICYmLi4uIGFyZ3MpCiAgewogICAgYXV0byBmID0gc3RkOjpkeW5hbWljX3BvaW50ZXJfY2FzdDx2YXJpYWRpY19mdW5jdGlvbjxBcmdzLi4uPj4oZl8pOwogICAgaWYgKGYpCiAgICB7CiAgICAgICgqZikoc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKICAgIH0KICB9Cgpwcml2YXRlOgogIHN0ZDo6c2hhcmVkX3B0cjxmdW5jdGlvbl93cmFwcGVyPiBmXzsKfTsKCmludCBtYWluKCkKewogIGRpc3BhdGNoZXIgZDsKICBzdGQ6OmZ1bmN0aW9uPHZvaWQoaW50KT4gZiA9IFtdKGludCBhKSB7IHN0ZDo6Y291dCA8PCBhIDw8ICJcbiI7IH07CiAgZC5yZWdpc3Rlcl9ldmVudChmKTsKICBkLnBvc3QoNDIpOwoKICByZXR1cm4gMDsKfQo=