[C++]给C++封装一个多播委托
一来闲的蛋疼,二来我们代码里面有一些fastdelegate的代码,在clang下面实在编译不过去,所以打算重造一个轮子,至少标准一点(换个编译器能编译过去...)....
废话不说,上代码:
// C++版的多播委托,使用boost::function
// 为了在各个编译器下面都能编译
// author:egmkang
#ifndef __ZEVENT_T_H__
#define __ZEVENT_T_H__
#include <boost/function.hpp>
#include <list>
template<typename T>
class zEventBaseT
{
public:
typedef T DelegateType;
typedef std::list<DelegateType*> ContainerType;
typedef typename ContainerType::iterator IterType;
inline void add(DelegateType *p)
{
if(p && !contains(p))
{
_impl_list.push_back(p);
}
}
inline void remove(DelegateType *p)
{
_impl_list.remove(p);
}
inline void operator +=(DelegateType *p)
{
add(p);
}
inline void operator -=(DelegateType *p)
{
remove(p);
}
protected:
zEventBaseT(){}
virtual ~zEventBaseT()
{
_impl_list.clear();
}
inline bool contains(DelegateType *p)
{
for(IterType iter = _impl_list.begin();
iter != _impl_list.end();
++iter)
{
if(*iter == p) return true;
}
return false;
}
protected:
ContainerType _impl_list;
};
template<typename T>
class zEventT;
#define EVENT_CALL(...) \
{ \
ContainerType& impl = this->_impl_list; \
for(IterType iter = impl.begin(); \
iter != impl.end(); \
++iter) \
{ \
(*(*iter))(__VA_ARGS__); \
} \
}
//FUNCTION_ARGS = 0
template<>
class zEventT<boost::function<void()> >:
public zEventBaseT<boost::function<void()> >
{
public:
void operator()()
{
EVENT_CALL();
}
};
//FUNCTION_ARGS = 1
template<typename P1>
class zEventT<boost::function<void(P1)> >:
public zEventBaseT<boost::function<void(P1)> >
{
public:
typedef typename zEventBaseT<boost::function<void(P1)> >::ContainerType ContainerType;
typedef typename zEventBaseT<boost::function<void(P1)> >::IterType IterType;
void operator()(P1 p1)
{
EVENT_CALL(p1);
}
};
//FUNCTION_ARGS = 2
template<typename P1,typename P2>
class zEventT<boost::function<void(P1,P2)> >:
public zEventBaseT<boost::function<void(P1,P2)> >
{
public:
typedef typename zEventBaseT<boost::function<void(P1,P2)> >::ContainerType ContainerType;
typedef typename zEventBaseT<boost::function<void(P1,P2)> >::IterType IterType;
void operator()(P1 p1,P2 p2)
{
EVENT_CALL(p1,p2);
}
};
//FUNCTION_ARGS = 3
template<typename P1,typename P2,typename P3>
class zEventT<boost::function<void(P1,P2,P3)> >:
public zEventBaseT<boost::function<void(P1,P2,P3)> >
{
public:
typedef typename zEventBaseT<boost::function<void(P1,P2,P3)> >::ContainerType ContainerType;
typedef typename zEventBaseT<boost::function<void(P1,P2,P3)> >::IterType IterType;
void operator()(P1 p1,P2 p2,P3 p3)
{
EVENT_CALL(p1,p2,p3);
}
};
//FUNCTION_ARGS = 4
template<typename P1,typename P2,typename P3,typename P4>
class zEventT<boost::function<void(P1,P2,P3,P4)> >:
public zEventBaseT<boost::function<void(P1,P2,P3,P4)> >
{
public:
typedef typename zEventBaseT<boost::function<void(P1,P2,P3,P4)> >::ContainerType ContainerType;
typedef typename zEventBaseT<boost::function<void(P1,P2,P3,P4)> >::IterType IterType;
void operator()(P1 p1,P2 p2,P3 p3,P4 p4)
{
EVENT_CALL(p1,p2,p3,p4);
}
};
#endif//__ZEVENT_T_H__
这里最多支持函数有四个参数,如果想要支持多的话,自己添上去就行.
使用该类的代码:
#include "zEvent.hpp"
#include <boost/bind.hpp>
#include <iostream>
#include <stdlib.h>
void printA(int a,int b)
{
std::cout << (a+b) << std::endl;
}
void printB(int a,int b)
{
std::cout << (a + b) << std::endl;
}
int main()
{
typedef zEventT<boost::function<void(int)> > PrintEvent;
typedef PrintEvent::DelegateType DelegateType;
PrintEvent _event;
DelegateType delegate1 = boost::bind(&printA,10,_1);
DelegateType delegate2 = boost::bind(&printB,12,_1);
_event += &delegate1;
_event += &delegate2;
_event(18);
std::cout << std::endl;
_event -= &delegate1;
_event(19);
system("pause");
return 0;
}
之所以委托链内存的是指针,原因有2:
1. 指针很容易比较
2. boost::function比较貌似有一点问题
用boost::function有一点好处,就是可以通过boost::bind完成一些复杂的功能:-),而且boost::function也是C++0x的内容之一
PS:
随手写了一个,至少兼容VC,GCC 4.4+,clang 2.8,有什么问题或者建议都可以留言,欢迎斧正.
clang真是一个好东西啊,准备把我们服务器的代码改的在clang下面可以编译过去,用clang做代码分析检查:-D
我自己对容器内存的顺序没要求,所以把容器换成set了哈,哈哈