之前实现过C++11的delegate,为了学习,手动实现一个03版本的。
没有可变模板参数,一切都是体力活。C++11下有function类,可以很轻松实现。于是从C++03开始,就从function造轮子。。
function轮子的主要代码如下:
#ifndef FUNCTION_CPLUSPLUS_03 #define FUNCTION_CPLUSPLUS_03 #include <iostream> using namespace std; namespace li { //关于仿函数...可以显式指定 如 function<void(testClass1::*)(int,string)> f3( &testClass1::operator(), &tc0 ); 或者function<void(testClass1::*)(int,string)> f3(&tc0); //关于拷贝构造等其他构造函数...太懒了...遇到坑再添加 //已经添加有cv属性的类成员的情况 //这里的function功能是没办法与C++11相比的,这里的function的主要目的是为实现delegate做类型擦除处理 #define TEMPLATE_PARA0 typename R #define TEMPLATE_PARA1 TEMPLATE_PARA0 ,typename P1 #define TEMPLATE_PARA2 TEMPLATE_PARA1 ,typename P2 #define TEMPLATE_PARA3 TEMPLATE_PARA2 ,typename P3 #define TEMPLATE_PARA4 TEMPLATE_PARA3 ,typename P4 #define TEMPLATE_PARA5 TEMPLATE_PARA4 ,typename P5 #define TEMPLATE_PARA6 TEMPLATE_PARA5 ,typename P6 #define TEMPLATE_PARA7 TEMPLATE_PARA6 ,typename P7 #define TEMPLATE_PARA8 TEMPLATE_PARA7 ,typename P8 #define TEMPLATE_PARA0_INS #define TEMPLATE_PARA1_INS P1 p1 #define TEMPLATE_PARA2_INS TEMPLATE_PARA1_INS , P2 p2 #define TEMPLATE_PARA3_INS TEMPLATE_PARA2_INS , P3 p3 #define TEMPLATE_PARA4_INS TEMPLATE_PARA3_INS , P4 p4 #define TEMPLATE_PARA5_INS TEMPLATE_PARA4_INS , P5 p5 #define TEMPLATE_PARA6_INS TEMPLATE_PARA5_INS , P6 p6 #define TEMPLATE_PARA7_INS TEMPLATE_PARA6_INS , P6 p7 #define TEMPLATE_PARA8_INS TEMPLATE_PARA7_INS , P6 p8 #define TEMPLATE_PARA0_N R #define TEMPLATE_PARA1_N TEMPLATE_PARA0_N , P1 #define TEMPLATE_PARA2_N TEMPLATE_PARA1_N , P2 #define TEMPLATE_PARA3_N TEMPLATE_PARA2_N , P3 #define TEMPLATE_PARA4_N TEMPLATE_PARA3_N , P4 #define TEMPLATE_PARA5_N TEMPLATE_PARA4_N , P5 #define TEMPLATE_PARA6_N TEMPLATE_PARA5_N , P6 #define TEMPLATE_PARA7_N TEMPLATE_PARA6_N , P7 #define TEMPLATE_PARA8_N TEMPLATE_PARA7_N , P8 enum FunType { Normal, Member }; template<typename R,typename P1=void,typename P2=void,typename P3=void, typename P4=void,typename P5=void,typename P6=void,typename P7=void,typename P8=void,typename P9=void> class function_impl; #define FUNCTION_IMPL(id) template<TEMPLATE_PARA##id> class function_impl<TEMPLATE_PARA##id##_N> { public: function_impl(){}; virtual R operator()(TEMPLATE_PARA##id##_INS)=0; virtual ~function_impl(){}; virtual FunType getFunType(){return Normal;} }; FUNCTION_IMPL(0) FUNCTION_IMPL(1) FUNCTION_IMPL(2) FUNCTION_IMPL(3) FUNCTION_IMPL(4) FUNCTION_IMPL(5) FUNCTION_IMPL(6) FUNCTION_IMPL(7) FUNCTION_IMPL(8) /**************************************************************************************************/ template<typename F> class function; #define TEMPLATE_PARA0_N1 #define TEMPLATE_PARA1_N1 P1 #define TEMPLATE_PARA2_N1 TEMPLATE_PARA1_N1 , P2 #define TEMPLATE_PARA3_N1 TEMPLATE_PARA2_N1 , P3 #define TEMPLATE_PARA4_N1 TEMPLATE_PARA3_N1 , P4 #define TEMPLATE_PARA5_N1 TEMPLATE_PARA4_N1 , P5 #define TEMPLATE_PARA6_N1 TEMPLATE_PARA5_N1 , P6 #define TEMPLATE_PARA7_N1 TEMPLATE_PARA6_N1 , P7 #define TEMPLATE_PARA8_N1 TEMPLATE_PARA7_N1 , P8 #define PARA_LIST0 #define PARA_LIST1 p1 #define PARA_LIST2 PARA_LIST1 ,p2 #define PARA_LIST3 PARA_LIST2 ,p3 #define PARA_LIST4 PARA_LIST3 ,p4 #define PARA_LIST5 PARA_LIST4 ,p5 #define PARA_LIST6 PARA_LIST5 ,p6 #define PARA_LIST7 PARA_LIST6 ,p7 #define PARA_LIST8 PARA_LIST7 ,p8 #define FUNCTION(id) template<TEMPLATE_PARA##id> class function<R(TEMPLATE_PARA##id##_N1)> :public function_impl<TEMPLATE_PARA##id##_N> { public: typedef R(*F)(TEMPLATE_PARA##id##_N1); function(F f):func_(f){ }; R operator()(TEMPLATE_PARA##id##_INS) {return func_(PARA_LIST##id);} void* getTarget()const { return (void*)*func_; } F func_; }; FUNCTION(0) FUNCTION(1) FUNCTION(2) FUNCTION(3) FUNCTION(4) FUNCTION(5) FUNCTION(6) FUNCTION(7) FUNCTION(8) /**************************************************************************************************/ #define FUNCTION_MEM(id,...) template<class C, TEMPLATE_PARA##id> class function<R(C::*)(TEMPLATE_PARA##id##_N1)__VA_ARGS__> :public function_impl<TEMPLATE_PARA##id##_N> { public: typedef R(C::*F)(TEMPLATE_PARA##id##_N1)__VA_ARGS__; typedef C* CPtr; function(F f,C*cp):func_(f),c_ptr(cp){}; function(C*cp):func_( &C::operator()),c_ptr(cp){}; R operator()(TEMPLATE_PARA##id##_INS) { return (c_ptr->*func_)(PARA_LIST##id); } FunType getFunType(){return Member;} F getTarget()const { return func_; } CPtr getTarCalssPtr() const { return c_ptr; } protected: F func_; CPtr c_ptr; }; FUNCTION_MEM(0) FUNCTION_MEM(1) FUNCTION_MEM(2) FUNCTION_MEM(3) FUNCTION_MEM(4) FUNCTION_MEM(5) FUNCTION_MEM(6) FUNCTION_MEM(7) FUNCTION_MEM(8) FUNCTION_MEM(0,const) FUNCTION_MEM(1,const) FUNCTION_MEM(2,const) FUNCTION_MEM(3,const) FUNCTION_MEM(4,const) FUNCTION_MEM(5,const) FUNCTION_MEM(6,const) FUNCTION_MEM(7,const) FUNCTION_MEM(8,const) FUNCTION_MEM(0,volatile) FUNCTION_MEM(1,volatile) FUNCTION_MEM(2,volatile) FUNCTION_MEM(3,volatile) FUNCTION_MEM(4,volatile) FUNCTION_MEM(5,volatile) FUNCTION_MEM(6,volatile) FUNCTION_MEM(7,volatile) FUNCTION_MEM(8,volatile) FUNCTION_MEM(0,const volatile) FUNCTION_MEM(1,const volatile) FUNCTION_MEM(2,const volatile) FUNCTION_MEM(3,const volatile) FUNCTION_MEM(4,const volatile) FUNCTION_MEM(5,const volatile) FUNCTION_MEM(6,const volatile) FUNCTION_MEM(7,const volatile) FUNCTION_MEM(8,const volatile) }; #endif
然后再来造delegate的轮子,代码如下:
#ifndef DELEGATE_CPLUSPLUS_03 #define DELEGATE_CPLUSPLUS_03 #include "function.hpp" #include <list> #include <iostream> using namespace std; namespace li { //此处参考 《Modern C++ Design》 一书,牛人牛书啊,不过这里暂时没用到,之前想的情况比较复杂,以为会用到,代码还是比较经典的,所有保留在此 /*判断类型之间能否相互转换*/ template<class T, class U> class Convert { static char Test(U); static int Test(...); static T MakeT(); public: enum { CanConvert =sizeof(Test(MakeT())) == sizeof(char) }; }; template<typename R=void,typename P1=void,typename P2=void,typename P3=void, typename P4=void,typename P5=void,typename P6=void,typename P7=void,typename P8=void,typename P9=void> class delegate; template<typename F,typename C> class deleMemHelper { public: deleMemHelper(F f,C*cptr):fun(f),c_ptr(cptr){} F fun; C*c_ptr; }; template<typename F,typename C> deleMemHelper<F,C> makeDeleMemHelper(F f,C*cp) { return deleMemHelper<F,C>(f,cp); } #define DELEGATE_CLASS(id) template<TEMPLATE_PARA##id> class delegate<R(TEMPLATE_PARA##id##_N1)> { public: typedef li::function_impl<TEMPLATE_PARA##id##_N> dele_func; typedef std::list<dele_func*> function_list; typedef R(*func_type)(TEMPLATE_PARA##id##_N1); typedef delegate<R(TEMPLATE_PARA##id##_N1)> this_type; delegate(){}; ~delegate() { clear(); } void clear() { for(typename function_list::iterator itr =func_list.begin();itr!= func_list.end(); itr++ ) { delete *itr; } func_list.clear(); } this_type& operator+=(func_type fun) { func_list.push_back(new function<R(TEMPLATE_PARA##id##_N1)>(fun)); return *this; } this_type& operator-=(func_type fun) { for( function_list::iterator itr = func_list.begin(); itr!= func_list.end(); ++itr ) { if((*itr)->getFunType()!=Normal) continue; func_type p =(func_type)( ((function<R(TEMPLATE_PARA##id##_N1)>*)(*itr))->getTarget()); if(p && *p==fun) { delete *itr; func_list.erase(itr); break; } } return *this; } template<class C,class B> this_type& operator+=(const deleMemHelper<R(C::*)(TEMPLATE_PARA##id##_N1),B>& delemh) { C* c_ptr = dynamic_cast<C*>(delemh.c_ptr); if(!c_ptr) return *this; func_list.push_back(new function<R(C::*)(TEMPLATE_PARA##id##_N1)>(delemh.fun, c_ptr)); return *this; } template<class C,class B> this_type& operator-=(const deleMemHelper<R(C::*)(TEMPLATE_PARA##id##_N1),B>& delemh) { for( function_list::iterator itr = func_list.begin(); itr!= func_list.end(); ++itr ) { if((*itr)->getFunType()==Normal) continue; function<R(C::*)(TEMPLATE_PARA##id##_N1)>*func = dynamic_cast<function<R(C::*)(TEMPLATE_PARA##id##_N1)>*>(*itr); if(func==NULL) continue; C*cp =func->getTarCalssPtr(); if(cp&& cp==delemh.c_ptr ) { if( func->getTarget() == delemh.fun ) { delete *itr; func_list.erase(itr); break; } } } return *this; } void operator()(TEMPLATE_PARA##id##_INS) { for (typename function_list::iterator itr = func_list.begin(); itr != func_list.end(); itr++) { try { (*(*itr))(PARA_LIST##id); } catch (exception ex) { } } } private: function_list func_list; }; DELEGATE_CLASS(0) DELEGATE_CLASS(1) DELEGATE_CLASS(2) DELEGATE_CLASS(3) DELEGATE_CLASS(4) DELEGATE_CLASS(5) DELEGATE_CLASS(6) DELEGATE_CLASS(7) DELEGATE_CLASS(8) }; #endif
测试用例如下:
#include "function.hpp" #include "delegate.hpp" #include <string> #include <iostream> using namespace std; using namespace li; void funTest(int a,string b) { cout<<"funTest"<<" "<<a<<endl; } class testClass { public: testClass(int i):i(i){} void funTest(int a,string b) { cout<<"testClass "<< i<<" "<<a <<" "<<b<<endl; } int i; }; class A { public: virtual void funTest(int a,string b) { cout<<"A虚函数测试 "<< " "<<a <<" "<<b<<endl; } }; class C:public A { public: void funTest(int a,string b) { cout<<"C虚函数测试 "<< " "<<a <<" "<<b<<endl; } }; class testClass1 { public: testClass1(int i):i(i){} void funTest(int a,string b) { cout<<"testClass1 "<< i<<" "<<a <<" "<<b<<endl; } void operator()(int a,string b) { cout<<"testClass1 operator() "<< i<<" "<<a <<" "<<b<<endl; } int i; }; int sft(int a, const string& b,double c) { cout<<a<<" "<< b<<" "<<c<<endl; return 3333; } int sft1(int a, const string& b,double c,C &) { return 3333; } int main(int argc, char* argv[]) { function<int(int, const string&,double)> f = sft; function<int(int, const string&,double,C&)> f1 = sft1; f(4,string("asdfasdfasdfasdfasdfasdfas"),.0333); testClass1 tc0(3); function<void(testClass1::*)(int,string)> f3( &testClass1::operator(), &tc0 ); f3(99,""); function<void(testClass1::*)(int,string)> f4(&tc0); f4(98,"d"); cout<<"*********************单个函数测试完*******************"<<endl; testClass tc(1); testClass tc1(2); testClass1 tc21(1); testClass1 tc22(2); C c; delegate<void(int,string)> de; de+=funTest; de+=makeDeleMemHelper(&testClass::funTest,&tc); de+=makeDeleMemHelper(&testClass::funTest,&tc1); de+=makeDeleMemHelper(&C::funTest,&c); de(3,"afasdfasdfas"); cout<<"***********************************************************"<<endl; de-=funTest; de+=makeDeleMemHelper(&testClass1::funTest,&tc21); de(4,"afasdfasdfas"); cout<<"***********************************************************"<<endl; de-=makeDeleMemHelper(&testClass::funTest,&tc); de+=makeDeleMemHelper(&testClass1::funTest,&tc22); de+=funTest; de(5,"afasdfasdfas"); cout<<"***********************************************************"<<endl; de-=makeDeleMemHelper(&testClass::funTest,&tc1); de-=makeDeleMemHelper(&testClass1::funTest,&tc22); de-=makeDeleMemHelper(&C::funTest,&c); de(6,"afasdfasdfas"); cout<<"***********************************************************"<<endl; de.clear(); de(7,"asdfa"); cout<<"*******************end end end************************"<<endl; return 0; }
测试编译器VS2010 ,测试结果如下:
详细代码说明如下:
未完待续。。。