C++03下的delegate实现-

之前实现过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 ,测试结果如下:

C++03下的delegate实现-

 

详细代码说明如下:

未完待续。。。

 

你可能感兴趣的:(delegate)