最近需要一个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); }

|