1 Star 0 Fork 0

fensnote/cosmos

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
function_message_bus.hpp 8.33 KB
一键复制 编辑 原始数据 按行查看 历史
qicosmos 提交于 2018-08-02 18:30 . Update function_message_bus.hpp
#include <string>
#include <map>
#include <functional>
#include <cassert>
#include "function_traits.hpp"
#include "type_name.hpp"
template <typename... Args, typename Func, std::size_t... Idx>
void for_each(const std::tuple<Args...>& t, Func&& f, std::index_sequence<Idx...>) {
(void)std::initializer_list<int> { (f(std::get<Idx>(t)), void(), 0)...};
}
struct FnKey {
std::string key;
};
class FunctionMsgBus {
public:
static FunctionMsgBus& get()
{
static FunctionMsgBus instance;
return instance;
}
template<typename Function, typename=std::enable_if_t<!std::is_member_function_pointer<Function>::value>>
void register_handler(const Function& f, std::string const & additional="")
{
using namespace std::placeholders;
auto key = get_key<Function>(additional);
check_duplicate(key);
invokers_[key] = { std::bind(&invoker<Function>::apply, f, _1, _2) };
}
template <typename Function, typename Self, typename = std::enable_if_t<std::is_member_function_pointer<Function>::value>>
void register_handler(Function f, Self* t, std::string const & additional ="") {
using namespace std::placeholders;
auto key = get_key<Function>(additional);
check_duplicate(key);
invokers_[key] = { std::bind(&invoker<Function>::template apply_mem<Self>, f, t, _1, _2) };
}
//non-void function
template <typename T, typename U, typename ... Args>
T call(U&& u, Args&& ... args)
{
std::string key = get_key(std::forward<U>(u), std::forward<Args>(args)...);
auto it = invokers_.find(key);
assert(it != invokers_.end());
T t;
call_impl(it, &t, std::forward<U>(u), std::forward<Args>(args)...);
return t;
}
//void function
template <typename U, typename ... Args>
void call(U&& u, Args&& ... args)
{
std::string key = get_key(std::forward<U>(u), std::forward<Args>(args)...);
auto it = invokers_.find(key);
assert(it != invokers_.end());
call_impl(it, nullptr, std::forward<U>(u), std::forward<Args>(args)...);
}
private:
FunctionMsgBus() {};
FunctionMsgBus(const FunctionMsgBus&) = delete;
FunctionMsgBus(FunctionMsgBus&&) = delete;
template <typename T, typename U, typename ... Args>
void call_impl(T it, void* ptr, U&& u, Args&& ... args){
auto args_tuple = get_args_tuple(std::integral_constant<bool, std::is_same<U, FnKey>::value>{},
std::forward<U>(u), std::forward<Args>(args)...);
using Tuple = decltype(args_tuple);
using storage_type = typename std::aligned_storage<sizeof(Tuple), alignof(Tuple)>::type;
storage_type data;
Tuple* tp = new (&data) Tuple;
*tp = args_tuple;
it->second(tp, ptr);
}
void check_duplicate(const std::string& key){
auto it = invokers_.find(key);
if(it!=invokers_.end())
assert("duplicate register");
}
template<typename Function>
std::string get_key(std::string const & additional) {
if(!additional.empty())
return additional;
using tuple_type = typename function_traits<Function>::bare_tuple_type;
auto key = get_name_from_tuple(tuple_type{});
return key;
}
template <typename U, typename ... Args>
std::enable_if_t<std::is_same<U, FnKey>::value, std::string> get_key(U&& u, Args&& ... args) {
return u.key;
}
template <typename U, typename ... Args>
std::enable_if_t<!std::is_same<U, FnKey>::value, std::string> get_key(U&& u, Args&& ... args) {
return get_name(std::forward<U>(u), std::forward<Args>(args)...);
}
template <typename U, typename ... Args>
auto get_args_tuple(std::true_type, U&& u, Args&& ... args)-> decltype(std::make_tuple(std::forward<Args>(args)...)) {
return std::make_tuple(std::forward<Args>(args)...);
}
template <typename U, typename ... Args>
auto get_args_tuple(std::false_type, U&& u, Args&& ... args) ->decltype(std::make_tuple(std::forward<U>(u), std::forward<Args>(args)...)){
return std::make_tuple(std::forward<U>(u), std::forward<Args>(args)...);
}
template<typename... Args>
std::string get_name(Args&&... args) {
std::string name = "";
std::initializer_list<int>{(name += type_name<Args>(), 0)...};
return name;
}
struct caller{
caller(std::string& name):name_(name){
}
template<typename T>
void operator()(const T& t){
name_+= type_name<T>();
}
std::string& name(){
return name_;
}
std::string& name_;
};
template<typename T>
std::string get_name_from_tuple(T t) {
std::string name = "";
for_each(t, caller{name}, std::make_index_sequence<std::tuple_size<T>::value>{});
return name;
}
template<typename Function>
struct invoker
{
static inline void apply(const Function& func, void* bl, void* result)
{
using tuple_type = typename function_traits<Function>::bare_tuple_type;
const tuple_type* tp = static_cast<tuple_type*>(bl);
call(func, *tp, result);
}
template<typename F, typename ... Args>
static typename std::enable_if<std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void*)
{
call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
}
template<typename F, typename ... Args>
static typename std::enable_if<!std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void* result)
{
auto r = call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
if(result)
*(decltype(r)*)result = r;
}
template<typename F, size_t... I, typename ... Args>
static auto call_helper(const F& f, const std::index_sequence<I...>&, const std::tuple<Args...>& tup)-> typename std::result_of<F(Args...)>::type
{
return f(std::get<I>(tup)...);
}
template <typename Self>
static inline void apply_mem(Function f, Self* self, void* bl, void* result)
{
using tuple_type = typename function_traits<Function>::bare_tuple_type;
const tuple_type* tp = static_cast<tuple_type*>(bl);
using return_type = typename function_traits<Function>::return_type;
call_mem(f, self, *tp, result, std::integral_constant<bool, std::is_void<return_type>::value>{});
}
template<typename F, typename Self, typename ... Args>
static void call_mem(F f, Self* self, const std::tuple<Args...>& tp, void*, std::true_type)
{
call_member_helper(f, self, std::make_index_sequence<sizeof...(Args)>{}, tp);
}
template<typename F, typename Self, typename ... Args>
static void call_mem(F f, Self* self, const std::tuple<Args...>& tp, void* result, std::false_type)
{
auto r = call_member_helper(f, self, std::make_index_sequence<sizeof...(Args)>{}, tp);
if(result)
*(decltype(r)*)result = r;
}
template<typename F, typename Self, size_t... I, typename ... Args>
static auto call_member_helper(F f, Self* self, const std::index_sequence<I...>&, const std::tuple<Args...>& tup)-> decltype((self->*f)(std::get<I>(tup)...))
{
return (self->*f)(std::get<I>(tup)...);
}
};
private:
std::map<std::string, std::function<void(void*, void*)>> invokers_;
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/fensnote/cosmos.git
git@gitee.com:fensnote/cosmos.git
fensnote
cosmos
cosmos
master

搜索帮助