才想起来像这样“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(),然后最外部加一层封装,隐藏参数个数选择的细节:
完整代码
代码下载 测试代码跟之前一样
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