一来闲的蛋疼,二来我们代码里面有一些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__
// 为了在各个编译器下面都能编译
// 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 ;
}
#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了哈,哈哈