最近这段时间在仿造.net的部分库,写一个小型的C++类库。既然要模仿.net,那么委托是少不了的。
本来想直接使用boost::function, 但他没有实现operator==, 不太好实现多播委托。
boost :: signal 库需要调用编译好的动态库,不符合我的要求,而且他的disconnect的实现让人很不满意,必须把在在调用connect时返回的哪个对象保存起来才能调用disconnect;
没办法,只有仿造function库重新写了一共,好像我考虑的系统只是2000以后的系统,和vc7.0以后的编译器,不用考虑编译器不支持偏特化的问题,今天捣鼓了一天,总算弄出来了
先看看如何使用
class A
{
public:
void operator()(int&)
{
cout<<"A::operator()"<<endl;
}
void fun(int&)
{
cout<<"A::fun"<<endl;
}
};
void fun(int&)
{
cout<<"fun"<<endl;
}
int main()
{
typedef winst::Delegate<void(int&)> Function;
int i = 1;
A a;
Function dop(&a);
Function dmem(&A::fun, &a);
Function dfree(fun);
dop(i);
dmem(i);
dfree(i);
dop += Function::MakeDelegate(fun);
dmem += Function::MakeDelegate(fun);
dop(i);
dmem(i);
cout<< (dop == dmem) <<endl;
cout<< dop.Have(Function::MakeDelegate(fun))<<endl;
dmem -= Function::MakeDelegate(&A::fun, &a);
dmem(i);
}
实现的关键是
class Holder;
class A
{
public:
void fun(){};
};
A a;
Holder* holderPtr reinterpret_cast<Holder*>(&a);
void(Holder::*f)(void) = &A::fun;
(holderPtr->*)()//调用的时a.fun();
当调用a.fun()时,实际上是相当于g_fun(&a)
只要g_fun,和a的地址正确,函数类型和参数类型不重要
这样就可以把函数对象,成员函数,自由函数保存下来
template<typename R>
class DelegateHolder<R(void)>
{
public:
typedef R(MemberFunHolder::* MemberFun)(void);
typedef R(*FreeFun)(void);
typedef DelegateHolder<R(void)> ThisType;
DelegateHolder(FreeFun fun)
{
MemberFun* f = reinterpret_cast<MemberFun*>(&fun);
fun_ = *f;
objPtr_ = 0;
}
template<typename T>
DelegateHolder(R(T::*fun)(void), T* objPtr)
{
objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);
fun_ = reinterpret_cast<MemberFun>(fun);
}
template<typename T>
DelegateHolder(T * objPtr)
{
objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);
fun_ = reinterpret_cast<MemberFun>(&T::operator());
}
。。。。。。。。
R operator()(void)
{
if(objPtr_ == 0)
{
FreeFun * f = reinterpret_cast<FreeFun*>(&fun_);
FreeFun fun = *f;
return fun();
}
else
{
return (objPtr_->*fun_)();
}
}
。。。。。。。。。。。。。。。
private:
MemberFunHolder * objPtr_;
MemberFun fun_;
};
还有一个问题是
class Arg1{};
class Arg2{};
class Arg3{};
template<typename A1 = Arg1, typename A2 = Arg2, typename A3 = Arg3>
class Test
{
public:
void p(){cout<<"0"<<endl;}
};
template<typename A1>
class Test<A1(void), Arg2, Arg3>
{
public:
void p() {cout<<"1"<<endl;}
};
template<typename A1, typename A2>
class Test<A1(A2)>
{
public:
void p() {cout<<"2"<<endl;}
};
Test<int(int)> t;
t.p(); // 2;
Test(int(void)> t2;
t2.p() //1
这样才能对“不同模板参数个数”的类实现特化。
下面时0参数实现的源码
class MemberFunHolder{};
namespace dele_arg
{
class Arg1{};
class Arg2{};
class Arg3{};
class Arg4{};
class Arg5{};
class Arg6{};
class Arg7{};
class Arg8{};
class Arg9{};
class Arg10{};
}
template<typename R,
typename Arg1 = dele_arg::Arg1,
typename Arg2 = dele_arg::Arg2,
typename Arg3 = dele_arg::Arg3,
typename Arg4 = dele_arg::Arg4,
typename Arg5 = dele_arg::Arg5,
typename Arg6 = dele_arg::Arg6,
typename Arg7 = dele_arg::Arg7,
typename Arg8 = dele_arg::Arg8,
typename Arg9 = dele_arg::Arg9,
typename Arg10 = dele_arg::Arg10
>
class DelegateHolder;
template<typename R,
typename Arg1 = dele_arg::Arg1,
typename Arg2 = dele_arg::Arg2,
typename Arg3 = dele_arg::Arg3,
typename Arg4 = dele_arg::Arg4,
typename Arg5 = dele_arg::Arg5,
typename Arg6 = dele_arg::Arg6,
typename Arg7 = dele_arg::Arg7,
typename Arg8 = dele_arg::Arg8,
typename Arg9 = dele_arg::Arg9,
typename Arg10 = dele_arg::Arg10
>
class Delegate;
template<typename R>
class DelegateHolder<R(void)>
{
public:
typedef R(MemberFunHolder::* MemberFun)(void);
typedef R(*FreeFun)(void);
typedef DelegateHolder<R(void)> ThisType;
DelegateHolder(const ThisType & other)
{
operator= (other);
}
DelegateHolder(FreeFun fun)
{
MemberFun* f = reinterpret_cast<MemberFun*>(&fun);
fun_ = *f;
objPtr_ = 0;
}
template<typename T>
DelegateHolder(R(T::*fun)(void), T* objPtr)
{
objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);
fun_ = reinterpret_cast<MemberFun>(fun);
}
template<typename T>
DelegateHolder(T * objPtr)
{
objPtr_ = reinterpret_cast<MemberFunHolder*>(objPtr);
fun_ = reinterpret_cast<MemberFun>(&T::operator());
}
bool operator== (const ThisType & other) const
{
return (objPtr_ == other.objPtr_) && (fun_ == other.fun_);
}
bool operator!= (const ThisType & other) const
{
return ! operator== (other);
}
R operator()(void)
{
if(objPtr_ == 0)
{
FreeFun * f = reinterpret_cast<FreeFun*>(&fun_);
FreeFun fun = *f;
return fun();
}
else
{
return (objPtr_->*fun_)();
}
}
DelegateHolder & operator= (const ThisType & other)
{
objPtr_ = other.objPtr_;
fun_ = other.fun_;
return *this;
}
private:
MemberFunHolder * objPtr_;
MemberFun fun_;
};
template<typename R>
class Delegate<R(void)>
{
typedef DelegateHolder<R(void)> Holder;
typedef R(*FreeFun)(void);
typedef Delegate<R(void)> ThisType;
public:
Delegate(const ThisType& other)
:holder_(other.holder_)
{
}
Delegate(Holder & holder)
:holder_(holder)
{
}
Delegate(FreeFun fun)
:holder_(fun)
{
}
template<typename T>
Delegate(R(T::*fun)(void), T* objPtr)
:holder_(fun, objPtr)
{
}
template<typename T>
Delegate(T * objPtr)
:holder_(objPtr)
{
}
Delegate & operator= (ThisType & other)
{
holder_ = other.holder_;
return *this;
}
Delegate operator= (const Holder & holder)
{
holder_ = holder;
return *this;
}
bool operator== (const ThisType& other) const
{
return holder_ == other.holder_;
}
bool operator != (const ThisType& other) const
{
return ! operator== (other);
}
bool operator== (const Holder & holder) const
{
return holder_ == holder;
}
bool operator!= (const Holder & holder) const
{
return ! operator== (holder)
}
R operator() ()
{
return holder_();
}
private:
Holder holder_;
};
template<>
class Delegate<void(void)>
{
typedef DelegateHolder<void(void)> Holder;
typedef void(*FreeFun)(void);
typedef Delegate<void(void)> ThisType;
public:
Delegate(ThisType & other)
:holderList_(other.holderList_)
{
}
Delegate(Holder& holder)
{
operator+= (holder);
}
Delegate(FreeFun fun)
{
Holder holder(fun);
operator += (holder);
}
template<typename T>
Delegate(void(T::*fun)(void), T* objPtr)
{
Holder holder(fun, objPtr);
operator += (holder);
}
template<typename T>
Delegate(T * objPtr)
{
Holder holder(objPtr);
operator += (holder);
}
void operator += (Holder & holder)
{
if( FindHolder(holder) == false )
{
holderList_.push_back(holder);
}
}
void operator -= (Holder & holder)
{
holderList_.remove(holder);
}
bool operator == (const ThisType & other) const
{
return holderList_ == other.holderList_;
}
bool operator != (const ThisType & other) const
{
return ! operator== (other);
}
bool operator == (const Holder & holder) const
{
if( holderList_.size() != 1 )
{
return false;
}
return FindHolder(holder);
}
bool operator != (const Holder & holder) const
{
return !operator== (holder);
}
bool Have(Holder & holder)
{
return FindHolder(holder);
}
void operator() ()
{
foreach(Holder holder, holderList_)
{
holder();
}
}
public:
static Holder MakeDelegate(FreeFun fun)
{
return Holder(fun);
}
template<typename T>
static Holder MakeDelegate(void(T::*fun)(void), T* objPtr)
{
return Holder(fun, objPtr);
}
template<typename T>
static Holder MakeDelegate(T * objPtr)
{
return Holder(objPtr);
}
private:
bool FindHolder(const Holder & holderFind) const
{
foreach(Holder holder, holderList_)
{
if( holder == holderFind )
{
return true;
}
}
return false;
}
private:
List<Holder> holderList_;
};
最后的工作就是定义一些宏来简化复制过程,然后复制,修改,实现1-10个参数的情况。还有就是要注意对象生存期的问题