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 ,测试结果如下:

详细代码说明如下:

未完待续。。。

原文地址:https://www.cnblogs.com/lxzCode/p/3741335.html