Skip to content

Instantly share code, notes, and snippets.

@nyaocat
Last active February 15, 2018 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nyaocat/f25b04debd02dec9d5e4 to your computer and use it in GitHub Desktop.
Save nyaocat/f25b04debd02dec9d5e4 to your computer and use it in GitHub Desktop.
type-safe event holder
#include <iostream>
#include <string>
#include "signal.hpp"
struct event_A : public s::signal<int, int> {};
struct event_B : public s::signal<std::string, int, double> {};
int main() {
s::bind<event_A>([](int p1, int p2) {
std::cout << "event A handler: " << p1 << ", " << p2 << std::endl;
});
s::bind<event_A>([](int p1, int p2) {
std::cout << "another event A handler: " << p1 << ", " << p2 << std::endl;
});
s::bind<event_B>([](std::string p1, int p2, double p3) {
std::cout << "event B handler: " << p1 << ", " << p2 << ", " << p3<< std::endl;
});
s::emit<event_A>( 99, 100 );
s::emit<event_B>( "agepoyo", 10, 0.3 );
//s::emit<event_A>( true ); // error
}
#include <functional>
#include <memory>
#include <tuple>
#include <vector>
#include <type_traits>
#include <unordered_map>
#include <boost/any.hpp>
namespace s {
template<typename ... Types>
struct signal {
using function_type = std::function<void(Types...)>;
using tuple_type = std::tuple<Types...>;
};
template<typename T>
void* type_to_unique_value_helper() {
static int dummy = 0;
return static_cast<void*>(&dummy);
}
std::unordered_map<void*, std::vector<boost::any>>& signal_map() {
static std::unordered_map<void*, std::vector<boost::any>> m;
return m;
}
template<typename SIGNAL>
void bind(typename SIGNAL::function_type f) {
signal_map()[type_to_unique_value_helper<SIGNAL>()].emplace_back(f);
}
template<typename SIGNAL, typename ... Types>
void emit(Types ... args) {
static_assert(
std::is_convertible<std::tuple<Types...>, typename SIGNAL::tuple_type>::value,
"args unmatch");
for(auto& f : signal_map()[type_to_unique_value_helper<SIGNAL>()]) {
boost::any_cast<typename SIGNAL::function_type>(f)( args ... );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment