熟悉C#的人都清楚delegate,也清楚委托的作用。

实现观察者模式,在C++中的一种做法就是通过接口继承来实现,这无疑大大增加了耦合度。通过delegate变可以解除这种耦合。

下面是上班时间,偷偷实现的一个我的delegate。直接上码:

#include<list>
#include<functional>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
 
#ifdef _DEBUG
#define OUTPUT(info) cout<<info <<endl<<endl;
#else
#define OUTPUT(info)
#endif

namespace lixz
{
    template<class C,typename R,typename ...Args>
    class _delegate_class_mem
    {
    public: 
        typedef R(C::*class_func_type)(Args...);
          
        _delegate_class_mem(class_func_type fun, C* class_ptr) :_fun(fun), _class_ptr(class_ptr) {}

        R operator()(Args&&...args)
        {
            return (_class_ptr->*_fun)(args...);
        }

         
        bool operator== (const _delegate_class_mem<C, R, Args...>&other) const 
        {
            if (_class_ptr == other._class_ptr && _fun == other._fun) 
                return true; 
            return false;
        }
          
        template<typename T>
        bool operator==(const T&&)const
        {
            return false;
        }
        
    private:
        C*  _class_ptr;
        class_func_type _fun;

    };


template<typename ...T>
class delegate{ };
 

template<typename R, typename ...Args>
class delegate<R(Args...)>
{
public:
    typedef std::function<R(Args...)> dele_func;
    typedef std::list<dele_func> function_list;
    typedef R(*func_type)(Args...);
    typedef delegate<R(Args...)>  this_type;

     
    delegate()
    {   
        OUTPUT("function type:"<< typeid(R(Args...)).name())
        OUTPUT("args count:" << sizeof...(Args)) 
    };

    ~delegate()
    {
         func_list.clear();
    }
     

    this_type& operator -=(func_type fun)
    {   
        auto itr = std::find_if(func_list.begin(), func_list.end(), 
        [&](dele_func&f)->bool
        {
            auto _fun = f.target<R(*)(Args...)>();
            if (_fun && *_fun == fun)
            {
                return true; 
            }
            return false;
        });

        if (itr != func_list.end())
            func_list.erase(itr);

        return *this;
    }

    template<class C>
    this_type& operator -=(_delegate_class_mem<C, R, Args...>&& class_mem_h)
    {   
        auto itr = std::find_if(func_list.begin(), func_list.end(),
            [&](dele_func&f)->bool
        {
            auto _fun = f.target<_delegate_class_mem<C, R, Args...>>();
            if (_fun && *_fun == class_mem_h)
            {
                return true;
            }
            return false;
        });

         
        if (itr != func_list.end())
        {
            func_list.erase(itr);
        } 
        return *this;
    }


    this_type& operator +=(func_type fun)
    {
        func_list.push_back(fun);
        return *this;
    }
     
    template<class C>
    this_type& operator +=(_delegate_class_mem<C, R, Args...>&& class_mem_h)
    {
        func_list.push_back(class_mem_h);
        return *this;
    }
   
    void operator()(Args&&...args)
    {
         for (auto itr = func_list.begin(); itr != func_list.end(); itr++)
        {
            try
            {
                (*itr)(args...);
            }
            catch (exception ex)
            {
                //do something...
            }
        }
    }
     
  
private:
    function_list func_list;
};


template<typename C,typename R, typename ...Args> 
auto makeDelegateClassHelper(R(C::*class_func_type)(Args...), C* class_ptr) ->_delegate_class_mem<C, R, Args...>
{
    return _delegate_class_mem<C, R, Args...>(class_func_type, class_ptr);
}

};


以下是测试用例:
void testFun1(string str)
{
    cout << "testFun1=======:" << str << endl;
}

void testFun2(string str)
{
    cout << "testFun2=======:" << str << endl;
}

class testfunClass1
{
public:
    void testFun(string str)
    {
        cout << "testfunClass1::testFun=======:" << str << endl;
    }
};

class testfunClass2
{
public:
    void testFun(string str)
    {
        cout << "testfunClass2::testFun=======:" << str << endl;
    }
};

using namespace lixz;

int main(int argc, char**)
{ 

    testfunClass1 tsc1;
    testfunClass2 tsc2;
      delegate<void(string)> f;
      f += testFun1;
      f += testFun2;
     
      f += makeDelegateClassHelper(&testfunClass1::testFun, &tsc1);
       
      f( string("delegate test string!"));

       OUTPUT(".............................................")
      f -= testFun1;
      f(string("delegate test string2!"));
      OUTPUT(".............................................")
      f -= testFun2;
      f += testFun1;
      f -= makeDelegateClassHelper(&testfunClass1::testFun, &tsc1);
      f(string("delegate test string3!"));
      OUTPUT(".............................................")

          f += makeDelegateClassHelper(&testfunClass2::testFun, &tsc2);
      f(string("delegate test string4!"));
    return 0;
}

以下是测试结果输出:

以下省略一万字。。。。

 

posted on 2014-05-15 22:59  蜀山  阅读(5305)  评论(0编辑  收藏  举报