代码改变世界

C++事件机制实现的改进

2013-02-02 20:16  lierlier  阅读(614)  评论(0编辑  收藏  举报

才想起来像这样“return void();”也是合法的,所以这次给事件加上返回值支持,而且之前事件声明语法很难看:

1 Event(int, int) event;

改成大众喜闻乐见的样子:

1 Event<void (int, int)> event;

不过需要自己实现的代码就增多不少,已经不能称之为简洁了。首先考虑返回值怎么表示,可以这样:

 1 template<class P1>
 2 auto operator ()(P1 arg1) -> decltype(std::function<HandlerT>(arg1))
 3 {
 4     int j = m_handlers.size();
 5 
 6     for ( const auto& i : m_handlers )
 7     {
 8         if ( --j == 0 )
 9             return i.second(arg1);
10         else
11             i.second(arg1);
12     }
13 
14     return decltype(std::function<HandlerT>(arg1))();
15 }

但是看起来很繁琐,用类型萃取把返回值类型取出来,还可以顺便把参数个数、每个参数的类型提取,这对扩展很有用(现在只用到返回值类型和参数个数):

 1 // 萃取函数签名里的参数个数和返回值类型
 2 template<class R> struct ParamTraits { typedef void RetType; };
 3 template<class R> struct ParamTraits<R ()> { enum { num = 0 }; typedef R RetType; };
 4 template<class R, class P1> struct ParamTraits<R (P1)> { enum { num = 1 }; typedef R RetType; };
 5 template<class R, class P1, class P2> struct ParamTraits<R (P1, P2)> { enum { num = 2 }; typedef R RetType; };
 6 template<class R, class P1, class P2, class P3> struct ParamTraits<R (P1, P2, P3)> { enum { num = 3 }; typedef R RetType; };
 7 template<class R, class P1, class P2, class P3, class P4> struct ParamTraits<R (P1, P2, P3, P4)> { enum { num = 4 }; typedef R RetType; };
 8 template<class R, class P1, class P2, class P3, class P4, class P5> struct ParamTraits<R (P1, P2, P3, P4, P5)> { enum { num = 5 }; typedef R RetType; };
 9 template<class R, class P1, class P2, class P3, class P4, class P5, class P6> struct ParamTraits<R (P1, P2, P3, P4, P5, P6)> { enum { num = 6 }; typedef R RetType; };
10 template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7)> { enum { num = 7 }; typedef R RetType; };
11 template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8)> { enum { num = 8 }; typedef R RetType; };
12 template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8, P9)> { enum { num = 9 }; typedef R RetType; };
13 template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)> { enum { num = 10 }; typedef R RetType; };

现在成了这样:

 1 typedef typename Event_Private::ParamTraits<HandlerT>::RetType RetType;
 2 
 3 template<class P1>
 4 RetType operator ()(P1 arg1)
 5 {
 6     int j = m_handlers.size();
 7 
 8     for ( const auto& i : m_handlers )
 9     {
10         if ( --j == 0 )
11             return i.second(arg1);
12         else
13             i.second(arg1);
14     }
15 
16     return RetType();
17 }

到这里,已经完成事件返回值的支持了,事件执行后取得最后一个事件处理器的返回值,如果没有绑定过,就返回返回值类型的默认值。如果不显式支持绑定类成员函数的话,到这一步已经足够了,但是还是要做一下。由于必须使用std::bind,而又不能摆脱参数占位符_1、_2...,只有依靠参数个数自动选择模板来实现了:

 1 template<class HandlerT, int ParamNum> struct Helper {};    
 2 
 3 template<class HandlerT> struct Helper<HandlerT, 1>
 4 {
 5     template<class ObjT, class FuncT> 
 6     inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1))
 7     {
 8         return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1);
 9     }
10 }

把 Ret operator()(P1,P2,...,Pn) 也放进去,使之从事件接口只看到对应参数个数的operator(),然后最外部加一层封装,隐藏参数个数选择的细节:

完整代码

代码下载 测试代码跟之前一样

View Code
  1 ///////////////////////////////////////////////////////////////////////
  2 // 事件模板
  3 //
  4 // 版本: 1.2
  5 // 作者: Pear
  6 // 日期: 2013-2-2
  7 //
  8 // 说明: 事件可以有无返回值,支持0~10个参数;不判断事件处理函数是否已经绑定过;不是线程安全的;
  9 //
 10 // 使用:
 11 //
 12 //  void f1(int, int)
 13 //  {
 14 //      puts("f1()");
 15 //  }
 16 //  
 17 //  struct F2
 18 //  {
 19 //      F2() { puts("F2 construct"); }
 20 //      F2(const F2 &) { puts("F2 copy"); }
 21 //      F2(F2 &&) { puts("F2 move"); }
 22 //      F2& operator=(const F2 &)  { puts("F2 copy assign"); return *this; }
 23 //      F2& operator=(F2 &&)  { puts("F2 move assign"); return *this; }
 24 //  
 25 //      void f(int, int)
 26 //      {
 27 //          puts("f2()");
 28 //      }
 29 //  
 30 //      void fc(int, int) const
 31 //      {
 32 //          puts("f2c()");
 33 //      }
 34 //  };
 35 //  
 36 //  struct F3
 37 //  {
 38 //      F3() { puts("F3 construct"); }
 39 //      F3(const F3 &) { puts("F3 copy"); }
 40 //      F3(F3 &&) { puts("F3 move"); }
 41 //      F3& operator=(const F3 &)  { puts("F3 copy assign"); return *this; }
 42 //      F3& operator=(F3 &&)  { puts("F3 move assign"); return *this; }
 43 //  
 44 //      void operator ()(int, int) const
 45 //      {
 46 //          puts("f3()");
 47 //      }
 48 //  };
 49 //  
 50 //  int _tmain(int argc, _TCHAR* argv[])
 51 //  {
 52 //      Utility::Event<void (int, int)> e;
 53 //  
 54 //      // 一般函数
 55 //      e.addHandler(f1);
 56 //  
 57 //      int id = e.addHandler(&f1);                                    
 58 //      e.removeHandler(id);                                                // 移除事件处理函数
 59 //  
 60 //  
 61 //      // 成员函数
 62 //      using namespace std::placeholders;
 63 //  
 64 //      F2 f2;
 65 //      const F2 *pf2 = &f2;
 66 //  
 67 //      e.addHandler(bind(&F2::f, &f2, _1, _2));        // std::bind
 68 //      e.addHandler(&f2, &F2::f);
 69 //  
 70 //      e.addHandler(pf2, &F2::fc);                                    // 常量指针
 71 //  
 72 //      puts("----addHandler(f2, &F2::f)----");
 73 //      e.addHandler(f2, &F2::f);                                        // 对象拷贝构造
 74 //  
 75 //      puts("----addHandler(F2(), &F2::f)----");
 76 //      e.addHandler(F2(), &F2::f);                                    // 对象转移构造
 77 //  
 78 //      puts("--------");
 79 //  
 80 //  
 81 //      // 仿函数
 82 //      F3 f3;
 83 //      const F3 *pf3 = &f3;
 84 //  
 85 //      puts("----addHandler(f3)----");
 86 //      e.addHandler(f3);                                                        // 对象拷贝构造
 87 //  
 88 //      puts("----addHandler(F3())----");
 89 //      e.addHandler(F3());                                                    // 对象转移构造
 90 //      puts("--------");
 91 //  
 92 //      e.addHandler(ref(f3));                                            // 引用仿函数对象
 93 //      e.addHandler(ref(*pf3));                                        // 引用仿函数常量对象
 94 //  
 95 //      puts("--------");
 96 //  
 97 //      // Lambda表达式
 98 //      e.addHandler([](int, int) {
 99 //          puts("f4()");
100 //      });
101 //  
102 //      // 激发事件
103 //      e(1, 2);
104 //  
105 //      return 0;
106 //  }
107 //
108 /////////////////////////////////////////////////////////////////////////
109 
110 #pragma once
111 
112 #include <map>
113 #include <functional>
114 
115 
116 namespace Utility
117 {
118 
119     namespace Event_Private
120     {
121         // 萃取T ()函数类型的参数个数和返回值类型
122         template<class R> struct ParamTraits { typedef void RetType; };
123         template<class R> struct ParamTraits<R ()> { enum { num = 0 }; typedef R RetType; };
124         template<class R, class P1> struct ParamTraits<R (P1)> { enum { num = 1 }; typedef R RetType; };
125         template<class R, class P1, class P2> struct ParamTraits<R (P1, P2)> { enum { num = 2 }; typedef R RetType; };
126         template<class R, class P1, class P2, class P3> struct ParamTraits<R (P1, P2, P3)> { enum { num = 3 }; typedef R RetType; };
127         template<class R, class P1, class P2, class P3, class P4> struct ParamTraits<R (P1, P2, P3, P4)> { enum { num = 4 }; typedef R RetType; };
128         template<class R, class P1, class P2, class P3, class P4, class P5> struct ParamTraits<R (P1, P2, P3, P4, P5)> { enum { num = 5 }; typedef R RetType; };
129         template<class R, class P1, class P2, class P3, class P4, class P5, class P6> struct ParamTraits<R (P1, P2, P3, P4, P5, P6)> { enum { num = 6 }; typedef R RetType; };
130         template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7)> { enum { num = 7 }; typedef R RetType; };
131         template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8)> { enum { num = 8 }; typedef R RetType; };
132         template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8, P9)> { enum { num = 9 }; typedef R RetType; };
133         template<class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10> struct ParamTraits<R (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)> { enum { num = 10 }; typedef R RetType; };
134 
135         // 事件辅助类
136         template<class HandlerT, int ParamNum> struct Helper {};    
137         
138 
139         // 事件模板基类
140         template<class HandlerT>
141         class EventBase
142         {
143         protected:
144             typedef typename Event_Private::ParamTraits<HandlerT>::RetType RetType;
145 
146             int m_handlerId;
147             std::map<int, std::function<HandlerT>> m_handlers;
148 
149         public:
150             EventBase() : m_handlerId(0) {}
151 
152             template<class Func> int addHandler(Func func)
153             {
154                 m_handlers.emplace(m_handlerId, std::forward<Func>(func));
155                 return m_handlerId++;
156             }
157 
158             template<class ObjT, class Func> int addHandler(ObjT obj, Func func)
159             {
160                 m_handlers.emplace(m_handlerId, Event_Private::Helper<HandlerT, Event_Private::ParamTraits<HandlerT>::num>::getBind(std::forward<ObjT>(obj), std::forward<Func>(func)));
161                 return m_handlerId++;
162             }
163 
164             void removeHandler(int handlerId)
165             {
166                 m_handlers.erase(handlerId);
167             }
168         };
169 
170     } // namespace Event_Private
171 
172 
173     // 事件模板
174     //
175     template<class HandlerT>
176     struct Event : public Event_Private::Helper<HandlerT, Event_Private::ParamTraits<HandlerT>::num>::Event_
177     {
178     };
179 
180 
181     // 按调用参数个数区分的事件激发函数、类成员绑定对象
182     namespace Event_Private
183     {
184         using namespace std::placeholders;
185 
186         template<class HandlerT> struct Helper<HandlerT, 0>
187         {
188             template<class ObjT, class FuncT> 
189             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj)))
190             {
191                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj));
192             }
193 
194             struct Event_ : public EventBase<HandlerT>
195             {
196                 RetType operator ()()
197                 {
198                     int j = m_handlers.size();
199 
200                     for ( const auto& i : m_handlers )
201                     {
202                         if ( --j == 0 )
203                             return i.second();
204                         else
205                             i.second();
206                     }
207 
208                     return RetType();
209                 }
210             };
211         };
212 
213         template<class HandlerT> struct Helper<HandlerT, 1>
214         {
215             template<class ObjT, class FuncT> 
216             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1))
217             {
218                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1);
219             }
220 
221             struct Event_ : public EventBase<HandlerT>
222             {
223                 template<class P1>
224                 RetType operator ()(P1 arg1)
225                 {
226                     int j = m_handlers.size();
227 
228                     for ( const auto& i : m_handlers )
229                     {
230                         if ( --j == 0 )
231                             return i.second(arg1);
232                         else
233                             i.second(arg1);
234                     }
235 
236                     return RetType();
237                 }
238             };
239         };
240 
241         template<class HandlerT> struct Helper<HandlerT, 2>
242         {
243             template<class ObjT, class FuncT> 
244             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2))
245             {
246                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2);
247             }
248 
249             struct Event_ : public EventBase<HandlerT>
250             {
251                 template<class P1, class P2>
252                 RetType operator ()(P1 arg1, P2 arg2)
253                 {
254                     int j = m_handlers.size();
255 
256                     for ( const auto& i : m_handlers )
257                     {
258                         if ( --j == 0 )
259                             return i.second(arg1, arg2);
260                         else
261                             i.second(arg1, arg2);
262                     }
263 
264                     return RetType();
265                 }
266             };
267         };
268 
269         template<class HandlerT> struct Helper<HandlerT, 3>
270         {
271             template<class ObjT, class FuncT> 
272             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3))
273             {
274                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3);
275             }
276 
277             struct Event_ : public EventBase<HandlerT>
278             {
279                 template<class P1, class P2, class P3>
280                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3)
281                 {
282                     int j = m_handlers.size();
283 
284                     for ( const auto& i : m_handlers )
285                     {
286                         if ( --j == 0 )
287                             return i.second(arg1, arg2, arg3);
288                         else
289                             i.second(arg1, arg2, arg3);
290                     }
291 
292                     return RetType();
293                 }
294             };
295         };
296 
297         template<class HandlerT> struct Helper<HandlerT, 4>
298         {
299             template<class ObjT, class FuncT> 
300             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4))
301             {
302                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4);
303             }
304 
305             struct Event_ : public EventBase<HandlerT>
306             {
307                 template<class P1, class P2, class P3, class P4>
308                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4)
309                 {
310                     int j = m_handlers.size();
311 
312                     for ( const auto& i : m_handlers )
313                     {
314                         if ( --j == 0 )
315                             return i.second(arg1, arg2, arg3, arg4);
316                         else
317                             i.second(arg1, arg2, arg3, arg4);
318                     }
319 
320                     return RetType();
321                 }
322             };
323         };
324 
325         template<class HandlerT> struct Helper<HandlerT, 5>
326         {
327             template<class ObjT, class FuncT> 
328             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5))
329             {
330                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5);
331             }
332 
333             struct Event_ : public EventBase<HandlerT>
334             {
335                 template<class P1, class P2, class P3, class P4, class P5>
336                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
337                 {
338                     int j = m_handlers.size();
339 
340                     for ( const auto& i : m_handlers )
341                     {
342                         if ( --j == 0 )
343                             return i.second(arg1, arg2, arg3, arg4, arg5);
344                         else
345                             i.second(arg1, arg2, arg3, arg4, arg5);
346                     }
347 
348                     return RetType();
349                 }
350             };
351         };
352 
353         template<class HandlerT> struct Helper<HandlerT, 6>
354         {
355             template<class ObjT, class FuncT> 
356             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6))
357             {
358                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6);
359             }
360 
361             struct Event_ : public EventBase<HandlerT>
362             {
363                 template<class P1, class P2, class P3, class P4, class P5, class P6>
364                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
365                 {
366                     int j = m_handlers.size();
367 
368                     for ( const auto& i : m_handlers )
369                     {
370                         if ( --j == 0 )
371                             return i.second(arg1, arg2, arg3, arg4, arg5, arg6);
372                         else
373                             i.second(arg1, arg2, arg3, arg4, arg5, arg6);
374                     }
375 
376                     return RetType();
377                 }
378             };
379         };
380 
381         template<class HandlerT> struct Helper<HandlerT, 7>
382         {
383             template<class ObjT, class FuncT> 
384             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7))
385             {
386                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7);
387             }
388 
389             struct Event_ : public EventBase<HandlerT>
390             {
391                 template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
392                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7)
393                 {
394                     int j = m_handlers.size();
395 
396                     for ( const auto& i : m_handlers )
397                     {
398                         if ( --j == 0 )
399                             return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
400                         else
401                             i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
402                     }
403 
404                     return RetType();
405                 }
406             };
407         };
408 
409         template<class HandlerT> struct Helper<HandlerT, 8>
410         {
411             template<class ObjT, class FuncT> 
412             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8))
413             {
414                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8);
415             }
416 
417             struct Event_ : public EventBase<HandlerT>
418             {
419                 template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
420                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8)
421                 {
422                     int j = m_handlers.size();
423 
424                     for ( const auto& i : m_handlers )
425                     {
426                         if ( --j == 0 )
427                             return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
428                         else
429                             i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
430                     }
431 
432                     return RetType();
433                 }
434             };
435         };
436 
437         template<class HandlerT> struct Helper<HandlerT, 9>
438         {
439             template<class ObjT, class FuncT> 
440             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9))
441             {
442                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9);
443             }
444 
445             struct Event_ : public EventBase<HandlerT>
446             {
447                 template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
448                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9)
449                 {
450                     int j = m_handlers.size();
451 
452                     for ( const auto& i : m_handlers )
453                     {
454                         if ( --j == 0 )
455                             return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
456                         else
457                             i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
458                     }
459 
460                     return RetType();
461                 }
462             };
463         };
464 
465         template<class HandlerT> struct Helper<HandlerT, 10>
466         {
467             template<class ObjT, class FuncT> 
468             inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10))
469             {
470                 return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10);
471             }
472 
473             struct Event_ : public EventBase<HandlerT>
474             {
475                 template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
476                 RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9, P10 arg10)
477                 {
478                     int j = m_handlers.size();
479 
480                     for ( const auto& i : m_handlers )
481                     {
482                         if ( --j == 0 )
483                             return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
484                         else
485                             i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
486                     }
487 
488                     return RetType();
489                 }
490             };
491         };
492 
493     } // namespace Event_Private
494 
495 } // namespace Utility