程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++事件機制實現的改進,事件機制改進

C++事件機制實現的改進,事件機制改進

編輯:C++入門知識

C++事件機制實現的改進,事件機制改進


才想起來像這樣“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
//
// 說明: 事件可以有無返回值,支持0~10個參數;不判斷事件處理函數是否已經綁定過;不是線程安全的;
//
// 使用:
//
//  void f1(int, int)
//  {
//      puts("f1()");
//  }
//  
//  struct F2
//  {
//      F2() { puts("F2 construct"); }
//      F2(const F2 &) { puts("F2 copy"); }
//      F2(F2 &&) { puts("F2 move"); }
//      F2& operator=(const F2 &)  { puts("F2 copy assign"); return *this; }
//      F2& operator=(F2 &&)  { puts("F2 move assign"); return *this; }
//  
//      void f(int, int)
//      {
//          puts("f2()");
//      }
//  
//      void fc(int, int) const
//      {
//          puts("f2c()");
//      }
//  };
//  
//  struct F3
//  {
//      F3() { puts("F3 construct"); }
//      F3(const F3 &) { puts("F3 copy"); }
//      F3(F3 &&) { puts("F3 move"); }
//      F3& operator=(const F3 &)  { puts("F3 copy assign"); return *this; }
//      F3& operator=(F3 &&)  { puts("F3 move assign"); return *this; }
//  
//      void operator ()(int, int) const
//      {
//          puts("f3()");
//      }
//  };
//  
//  int _tmain(int argc, _TCHAR* argv[])
//  {
//      Utility::Event<void (int, int)> e;
//  
//      // 一般函數
//      e.addHandler(f1);
//  
//      int id = e.addHandler(&f1);                                    
//      e.removeHandler(id);                                                // 移除事件處理函數
//  
//  
//      // 成員函數
//      using namespace std::placeholders;
//  
//      F2 f2;
//      const F2 *pf2 = &f2;
//  
//      e.addHandler(bind(&F2::f, &f2, _1, _2));        // std::bind
//      e.addHandler(&f2, &F2::f);
//  
//      e.addHandler(pf2, &F2::fc);                                    // 常量指針
//  
//      puts("----addHandler(f2, &F2::f)----");
//      e.addHandler(f2, &F2::f);                                        // 對象拷貝構造
//  
//      puts("----addHandler(F2(), &F2::f)----");
//      e.addHandler(F2(), &F2::f);                                    // 對象轉移構造
//  
//      puts("--------");
//  
//  
//      // 仿函數
//      F3 f3;
//      const F3 *pf3 = &f3;
//  
//      puts("----addHandler(f3)----");
//      e.addHandler(f3);                                                        // 對象拷貝構造
//  
//      puts("----addHandler(F3())----");
//      e.addHandler(F3());                                                    // 對象轉移構造
//      puts("--------");
//  
//      e.addHandler(ref(f3));                                            // 引用仿函數對象
//      e.addHandler(ref(*pf3));                                        // 引用仿函數常量對象
//  
//      puts("--------");
//  
//      // Lambda表達式
//      e.addHandler([](int, int) {
//          puts("f4()");
//      });
//  
//      // 激發事件
//      e(1, 2);
//  
//      return 0;
//  }
//
/////////////////////////////////////////////////////////////////////////

#pragma once

#include <map>
#include <functional>


namespace Utility
{

    namespace Event_Private
    {
        // 萃取T ()函數類型的參數個數和返回值類型
        template<class R> struct ParamTraits { typedef void RetType; };
        template<class R> struct ParamTraits<R ()> { enum { num = 0 }; typedef R RetType; };
        template<class R, class P1> struct ParamTraits<R (P1)> { enum { num = 1 }; typedef R RetType; };
        template<class R, class P1, class P2> struct ParamTraits<R (P1, P2)> { enum { num = 2 }; typedef R RetType; };
        template<class R, class P1, class P2, class P3> struct ParamTraits<R (P1, P2, P3)> { enum { num = 3 }; typedef R RetType; };
        template<class R, class P1, class P2, class P3, class P4> struct ParamTraits<R (P1, P2, P3, P4)> { enum { num = 4 }; typedef R RetType; };
        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; };
        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; };
        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; };
        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; };
        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; };
        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; };

        // 事件輔助類
        template<class HandlerT, int ParamNum> struct Helper {};    
        

        // 事件模板基類
        template<class HandlerT>
        class EventBase
        {
        protected:
            typedef typename Event_Private::ParamTraits<HandlerT>::RetType RetType;

            int m_handlerId;
            std::map<int, std::function<HandlerT>> m_handlers;

        public:
            EventBase() : m_handlerId(0) {}

            template<class Func> int addHandler(Func func)
            {
                m_handlers.emplace(m_handlerId, std::forward<Func>(func));
                return m_handlerId++;
            }

            template<class ObjT, class Func> int addHandler(ObjT obj, Func func)
            {
                m_handlers.emplace(m_handlerId, Event_Private::Helper<HandlerT, Event_Private::ParamTraits<HandlerT>::num>::getBind(std::forward<ObjT>(obj), std::forward<Func>(func)));
                return m_handlerId++;
            }

            void removeHandler(int handlerId)
            {
                m_handlers.erase(handlerId);
            }
        };

    } // namespace Event_Private


    // 事件模板
    //
    template<class HandlerT>
    struct Event : public Event_Private::Helper<HandlerT, Event_Private::ParamTraits<HandlerT>::num>::Event_
    {
    };


    // 按調用參數個數區分的事件激發函數、類成員綁定對象
    namespace Event_Private
    {
        using namespace std::placeholders;

        template<class HandlerT> struct Helper<HandlerT, 0>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj)))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj));
            }

            struct Event_ : public EventBase<HandlerT>
            {
                RetType operator ()()
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second();
                        else
                            i.second();
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 1>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1>
                RetType operator ()(P1 arg1)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1);
                        else
                            i.second(arg1);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 2>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2>
                RetType operator ()(P1 arg1, P2 arg2)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2);
                        else
                            i.second(arg1, arg2);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 3>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3);
                        else
                            i.second(arg1, arg2, arg3);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 4>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4);
                        else
                            i.second(arg1, arg2, arg3, arg4);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 5>
        {
            template<class ObjT, class FuncT> 
            inline static auto getBind(ObjT obj, FuncT func) -> decltype(std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 6>
        {
            template<class ObjT, class FuncT> 
            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))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5, class P6>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5, arg6);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5, arg6);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 7>
        {
            template<class ObjT, class FuncT> 
            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))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 8>
        {
            template<class ObjT, class FuncT> 
            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))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 9>
        {
            template<class ObjT, class FuncT> 
            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))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
                    }

                    return RetType();
                }
            };
        };

        template<class HandlerT> struct Helper<HandlerT, 10>
        {
            template<class ObjT, class FuncT> 
            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))
            {
                return std::bind(std::forward<FuncT>(func), std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10);
            }

            struct Event_ : public EventBase<HandlerT>
            {
                template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
                RetType operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9, P10 arg10)
                {
                    int j = m_handlers.size();

                    for ( const auto& i : m_handlers )
                    {
                        if ( --j == 0 )
                            return i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
                        else
                            i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
                    }

                    return RetType();
                }
            };
        };

    } // namespace Event_Private

} // namespace Utility

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved