Any.h:
#pragma once
#include <memory>
#include <typeindex>
/*
类似于boost Any类的实现
*/
using namespace std;
struct Any {
public:
Any(void) :m_tpIndex(type_index(typeid(void))) {}
Any(Any& that) :m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
Any(Any&& that) :m_ptr(move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}
// 创建智能指针时,对于一般的类型,通过decay来移除引用和CV符,从而获取原始类型
template<typename U, class = typename enable_if<!is_same<typename decay<U>::type, Any>::value, U>::type>
Any(U &&value) : m_ptr(new Derived<typename decay<U>::type>(forward<U>(value))), m_tpIndex(type_index(typeid(typename decay<U>::type))) {}
bool IsNull() const { return !bool(m_ptr); }
template<class U>bool Is() const {
return m_tpIndex == type_index(typeid(U));
}
// 将Any转换成实际的类型
template<class U>
U& AnyCast()
{
if (!Is<U>())
{
cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << endl;
throw bad_cast();
}
auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
return derived->m_value;
}
Any operator=(const Any& a)
{
if (m_ptr == a.m_ptr)
return *this;
m_ptr = a.Clone();
m_tpIndex = a.m_tpIndex;
return *this;
}
private:
struct Base;
typedef unique_ptr<Base> BasePtr;
struct Base
{
virtual ~Base() {}
virtual BasePtr Clone() const = 0;
};
template<typename T>
struct Derived :Base
{
template<typename U>
Derived(U&& value) :m_value(forward<U>(value)) {}
BasePtr Clone() const {
return BasePtr(new Derived<T>(m_value));
}
T m_value;
};
BasePtr Clone() const
{
if (m_ptr != nullptr)
{
return m_ptr->Clone();
}
return nullptr;
}
BasePtr m_ptr;
type_index m_tpIndex;
};
function_traits.h:
#pragma once
#include <functional>
#include <tuple>
#include <iostream>
using namespace std;
template <typename T>
struct function_traits;
template<typename Ret,typename...Args>
struct function_traits<Ret(Args...)>
{
public:
enum{arity=sizeof...(Args) };
typedef Ret function_type(Args...);
typedef Ret return_type;
using stl_function_type = function<function_type>;
typedef Ret(*pointer)(Args...);
template<size_t I>
struct args
{
static_assert(I < arity, "index is out of range,index must less than sizeof Args");
using type = typename tuple_element<I, tuple<Args...>>::type;
};
};
//函数指针
template<typename Ret,typename...Args>
struct function_traits<Ret(*)(Args...)>:function_traits<Ret(Args...)>{};
// std::function
template <typename Ret,typename... Args>
struct function_traits<function<Ret(Args...)>>:function_traits<Ret(Args...)>{};
//member function
#define FUNCTION_TRAITS(...) \
template<typename ReturnType,typename ClassType,typename...Args>\
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__>:\
function_traits<ReturnType(Args...)>{};
FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)
//函数对象
template<typename Callable>
struct function_traits:function_traits<decltype(&Callable::operator())>{};
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type > (lambda);
}
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(forward<Function>(lambda));
}
template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
{
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
NonCopyable.h:
#pragma once
class NonCopyable
{
protected:
NonCopyable() = default;
~NonCopyable() = default;
// 禁用复制构造
NonCopyable(const NonCopyable&) = delete;
// 禁用赋值构造
NonCopyable& operator = (const NonCopyable&) = delete;
};
MessageBus.h:
#pragma once
#include <string>
#include <functional>
#include <map>
#include "Any.h"
#include "function_traits.h"
#include "NonCopyable.h"
using namespace std;
class MessageBus :NonCopyable
{
public:
//注册消息
template<typename F>
void Attach(F&& f, const string& strTopic = "")
{
auto func = to_function(forward<F>(f));
Add(strTopic, move(func));
}
// 发送消息
template<typename R>
void SendReq(const string& strTopic = "")
{
using function_type = function<R()>;
string strMsgType = strTopic + typeid(function_type).name();
auto range = m_map.equal_range(strMsgType);
for (Iterater it = range.first;it!= range.second;++it)
{
auto f = it->second.AnyCast<function_type>();
f();
}
}
template<typename R,typename... Args>
void SendReq(Args&&...args, const string& strTopic = "")
{
using function_type = function<R(Args...)>;
string strMsgType = strTopic + typeid(function_type).name();
auto range = m_map.equal_range(strMsgType);
for (Iterater it = range.first; it != range.second;++it)
{
auto f = it->second.AnyCast<function_type>();
f(forward<Args>(args)...);
}
}
//移除某个主题,需要主题和消息类型
template<typename R,typename...Args>
void Remove(const string& strTopic = "")
{
using function_type = function<R(Args...)>;//typename function_traits<void(Args)>::stl_function_type;
string strMsgType = strTopic + typeid(function_type).name();
int count = m_map.count(strMsgType);
auto range = m_map.equal_range(strMsgType);
m_map.erase(range.first, range.second);
}
private:
template<typename F>
void Add(const string& strTopic, F&& f)
{
string strMsgType = strTopic + typeid(F).name();
m_map.emplace(move(strMsgType), forward<F>(f));
}
private:
multimap<string, Any> m_map;
typedef multimap<string, Any>::iterator Iterater;
};
测试代码:
// MessageBus.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include "MesssageBus.h"
using namespace std;
int main()
{
MessageBus bus;
// 注册消息
bus.Attach([](int a) {cout << "no reference" << a << endl; });
bus.Attach([](int& a) {cout << "lvalue reference" << a << endl; });
bus.Attach([](int&& a) {cout << "rvalue reference" << a << endl; });
bus.Attach([](const int& a) {cout << "const lvalue reference" << a << endl; });
bus.Attach([](int a) {cout << "no reference has return value and key" << a << endl; return a; },"a");
int i = 2;
// 发送消息
bus.SendReq<void,int>(2);
bus.SendReq<int, int>(2,"a");
bus.SendReq<void, int&>(i);
bus.SendReq<void, const int&>(2);
bus.SendReq<void, int&&>(2);
// 移除消息
bus.Remove<void,int>();
bus.Remove<int, int>("a");
bus.Remove<void, int&>();
bus.Remove<void,const int&>();
bus.Remove<void, int&&>();
// 发送消息
bus.SendReq<void, int>(2);
bus.SendReq<int, int>(2, "a");
bus.SendReq<void, int&>(i);
bus.SendReq<void, const int&>(2);
bus.SendReq<void, int&&>(2);
}
测试结果: