一个C++ delegate的实现

类别:编程语言 点击:0 评论:0 推荐:

最近需要一个C++delegate的实现,比较接近C#的delegate的用法。翻遍了boost,虽然有相近的东西,但是,始终使用起来问题多多:
function:的绑定方式倒也可以接受,成员函数调用的方式实在不爽。而且,同样的函数原型,native和member对应的function类型不同,不同class的相同原型的member function类型也不同。
signal:用起来不错,但是,一来内置了slot装置,又不便于介入干扰,二来,如何绑定一般的成员函数,不知道如何实现,只能绑定native function和functor。
bind:正是我所要的。可惜,占位符最大到3。
还有个siglib++的库,昨天才看到,为时已晚。粗略的看了一下,调用的方法,似乎也是拖泥带水。
不是我喜欢自己发明轮子,实在是迫不得已,只好自己写delegate了。手写的代码不长,贴在下面共享:
/*
copywrite:             别逗了(非典型秃子)
Description: C++的delegate实现。
可以随意复制、修改、分发、使用。不要说是自己的就可以了。^_^
*/
#ifndef DELEGATE_H
#define DELEGATE_H
#include "contract.h"//自己的一个库,只和下面的一些断言有关。
namespace nice
{
 template<typename T>
 class delegate;
//长长的宏,没办法:(
#define DELEGATE(TEMPLATE_ARGS, FUNCTION_ARGS, FUNCTION_PARA)\
 template< typename Ret TEMPLATE_ARGS >\
 class delegate<Ret (FUNCTION_ARGS)>\
 {\
  struct FunctionHolder\
  {\
   virtual Ret operator()(FUNCTION_ARGS) = 0;\
   virtual FunctionHolder* clone() const = 0;\
   virtual ~FunctionHolder(){};\
  };\
  FunctionHolder* h;\
\
  template<typename Functor>\
  struct FunctorHolder : public FunctionHolder\
  {\
   Functor* Fun;\
   FunctorHolder(Functor* nfun) : Fun(nfun){}\
   virtual Ret operator()(FUNCTION_ARGS)\
   {\
    return (*Fun)(FUNCTION_PARA);\
   }\
   virtual FunctionHolder* clone() const\
   {\
    return new FunctorHolder(*this);\
   }\
  };\
\
  template<typename U, typename MemFun>\
  struct MemHolder : public FunctionHolder\
  {  \
   U obj;\
   MemFun memFun;   \
\
   MemHolder(U aObj, MemFun amfun) \
    : obj(aObj), memFun(amfun){}\
\
    virtual Ret operator()(FUNCTION_ARGS) \
    {\
     return ((*obj).*memFun)(FUNCTION_PARA);\
    }\
    virtual FunctionHolder* clone() const\
    {\
     return new MemHolder(*this);\
    }\
  };\
  FunctionHolder* cloneHolder() const\
  {\
   if (connected())\
    return h->clone();\
   return NULL;\
  }\
 public:\
  delegate() : h(0)\
  {\
  }\
  ~delegate() \
  { \
   disconnect(); \
  }  \
\
  template<typename Functor>\
  delegate(Functor* nfun_) \
   : h(new FunctorHolder<Functor>(nfun_))\
  {\
  }\
\
  delegate(const delegate& rhs) : h(rhs.cloneHolder())\
  {}\
  template <typename U, typename MemFun>\
   delegate(U aObj, MemFun mFun) \
   : h(new MemHolder<U, MemFun>(aObj, mFun))\
  {  \
  }\
  delegate& operator=(const delegate& rhs)\
  {\
   if (&rhs != this)\
   {\
    disconnect();\
    h = rhs.cloneHolder();\
   }\
   return *this;\
  }\
  template<typename Functor>\
  void connect(Functor* nfun_)\
  {  \
   disconnect();\
   h = new FunctorHolder<Functor>(nfun_);\
  }\
\
  template <typename U, typename MemFun>\
   void connect(U aObj, MemFun mFun)\
  {\
   if (h) delete h;\
   h = new MemHolder<U, MemFun>(aObj, mFun);\
  }\
\
  void disconnect() \
  {  \
   if (connected()) delete h;  \
   h = 0; \
  } \
\
  bool connected() const\
  {\
   return (h != NULL);\
  }\
\
  Ret operator()(FUNCTION_ARGS)\
  {\
   pre_condition(connected());\
   return (*h)(FUNCTION_PARA);\
  }\
 };
//*/

#define TEMPLATE_ARGS_0
#define FUNCTION_ARGS_0
#define FUNCTION_PARA_0

#define TEMPLATE_ARGS_1         , typename T0
#define FUNCTION_ARGS_1      T0 t0
#define FUNCTION_PARA_1      t0

/* Defines Generate code:
for (int i = 2; i <= 50; i++)
{
 printf("#define TEMPLATE_ARGS_%d TEMPLATE_ARGS_%d, typename T%d\n", i, i - 1, i - 1) ;
 printf("#define FUNCTION_ARGS_%d FUNCTION_ARGS_%d, T%d t%d\n", i, i - 1, i - 1, i - 1);  
 printf("#define FUNCTION_PARA_%d FUNCTION_PARA_%d, t%d\n\n", i, i - 1, i - 1);    
};

for (int i = 0; i <= 50; ++i)
  printf("DELEGATE(TEMPLATE_ARGS_%d, FUNCTION_ARGS_%d, FUNCTION_PARA_%d)\n", i, i, i);
*/
 
//Auto Generate code:----------------------------------------------
#define TEMPLATE_ARGS_2 TEMPLATE_ARGS_1, typename T1
#define FUNCTION_ARGS_2 FUNCTION_ARGS_1, T1 t1
#define FUNCTION_PARA_2 FUNCTION_PARA_1, t1
....
#define TEMPLATE_ARGS_3 TEMPLATE_ARGS_2, typename T2
#define FUNCTION_ARGS_3 FUNCTION_ARGS_2, T2 t2
#define FUNCTION_PARA_3 FUNCTION_PARA_2, t2

#define TEMPLATE_ARGS_4 TEMPLATE_ARGS_3, typename T3
#define FUNCTION_ARGS_4 FUNCTION_ARGS_3, T3 t3
#define FUNCTION_PARA_4 FUNCTION_PARA_3, t3
...

DELEGATE(TEMPLATE_ARGS_0, FUNCTION_ARGS_0, FUNCTION_PARA_0)
DELEGATE(TEMPLATE_ARGS_1, FUNCTION_ARGS_1, FUNCTION_PARA_1)
DELEGATE(TEMPLATE_ARGS_2, FUNCTION_ARGS_2, FUNCTION_PARA_2)
DELEGATE(TEMPLATE_ARGS_3, FUNCTION_ARGS_3, FUNCTION_PARA_3)
...
};
#endif//end DELEGATE_H

测试用例:
CPPUNIT_TEST_SUITE_REGISTRATION(test_delegate);
using namespace nice;

int local_add(int a, int b)
{
 return a + b;
}

struct functor_add
{
 int m;
 int mem_add(int a, int b)
 {
  return a + b + m;
 }
};

struct functor_mul
{
 int m;
 int operator()(int a, int b)
 {
  return (a + b) * m;
 }
};


void test_delegate::testMain()
{
 typedef delegate<int(int, int)> testDele2;

 //默认ctor没有连接上
 testDele2 dele1;
 CPPUNIT_ASSERT(!dele1.connected());

 //connect
 testDele2 dele2(local_add);
 CPPUNIT_ASSERT(dele2.connected());

 //调用
 CPPUNIT_ASSERT(dele2(2, 3) == 5);

 //copy ctor
 testDele2 dele3 = dele2;
 CPPUNIT_ASSERT(dele3.connected());
 CPPUNIT_ASSERT(dele3(2, 3) == 5);

 //disconnect
 dele2.disconnect();
 CPPUNIT_ASSERT(!dele2.connected());
 
 //test clone
 CPPUNIT_ASSERT(dele3.connected());
 dele3(2, 3);
 CPPUNIT_ASSERT(dele3(2, 3) == 5);
 
 //assign
 dele2 = dele3;
 CPPUNIT_ASSERT(dele2(2, 3) == 5);

 //member function
 functor_add fctor;
 fctor.m = 7;
 dele2.connect(&fctor, &functor_add::mem_add);
 CPPUNIT_ASSERT(dele2(2, 3) == 12);

 //functor
 functor_mul fm;
 fm.m = 3;
 testDele2 dele4(&fm);
 CPPUNIT_ASSERT(dele4(2, 3) == 15);
 fm.m = 4;
 CPPUNIT_ASSERT(dele4(2, 3) == 20);

 dele2.connect(&fm);
}

本文地址:http://com.8s8s.com/it/it24903.htm