[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了哈,哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值