现在的位置: 首页 > 综合 > 正文

[C++]给C++封装一个多播委托

2012年11月21日 ⁄ 综合 ⁄ 共 3532字 ⁄ 字号 评论关闭

一来闲的蛋疼,二来我们代码里面有一些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了哈,哈哈

抱歉!评论已关闭.