123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- //
- #include <string>
- #include <map>
- #include <functional>
- namespace CXXHelper
- {
- template <typename _Ret, typename _Key, typename... Args>
- class Dispatch
- {
- protected:
- std::map <_Key, std::function <_Ret (Args...)> > m_handlers;
- public:
- Dispatch () { }
- Dispatch (Dispatch && from)
- {
- m_handlers.swap (from.m_handlers);
- }
- Dispatch (const Dispatch & from)
- {
- from.CopyTo (*this);
- }
- Dispatch & operator = (const Dispatch & from)
- {
- from.CopyTo (*this);
- return (*this);
- }
- Dispatch & operator = (Dispatch && from)
- {
- m_handlers.swap (from.m_handlers);
- return (*this);
- }
- void swap (Dispatch & from)
- {
- m_handlers.swap (from.m_handlers);
- }
- void CopyTo (Dispatch & to) const
- {
- to.m_handlers = m_handlers;
- }
- void Release ()
- {
- m_handlers.clear ();
- }
- auto begin ()
- {
- return m_handlers.begin ();
- }
- auto end ()
- {
- return m_handlers.end ();
- }
- auto begin () const
- {
- return m_handlers.cbegin ();
- }
- auto end () const
- {
- return m_handlers.cend ();
- }
- public:
- template <typename U = _Ret>
- std::enable_if_t <! std::is_void <U>::value, U>
- operator () (const _Key k, Args... arg)
- {
- return Invoke (k, arg...);
- }
- template <typename U = _Ret>
- std::enable_if_t <std::is_void <U>::value, U>
- operator () (Args... arg)
- {
- Invoke (arg...);
- }
- template <typename U = _Ret>
- std::enable_if_t <! std::is_void <U>::value, U>
- Invoke (const _Key k, Args... arg)
- {
- auto Iter = m_handlers.find (k);
- if (Iter != m_handlers.end ())
- {
- return (*Iter).second (arg...);
- }
- return U { };
- }
- template <typename U = _Ret>
- std::enable_if_t <std::is_void <U>::value, U>
- Invoke (const _Key k, Args... arg)
- {
- auto Iter = m_handlers.find (k);
- if (Iter != m_handlers.end ())
- {
- (*Iter).second (arg...);
- }
- }
- public:
- inline void RemoveAll ()
- {
- Release ();
- }
- inline bool IsEmpty () const
- {
- return m_handlers.empty ();
- }
- inline int GetSize () const
- {
- return (int)m_handlers.size ();
- }
- inline void AppendFrom (const Dispatch & from)
- {
- for (auto h : from.m_handlers)
- this->m_handlers.push_back (h);
- }
- public:
- Dispatch & operator += (Dispatch & from)
- {
- AppendFrom (from);
- return (*this);
- }
- public:
- template <typename TA>
- Dispatch & operator += (TA v)
- {
- Push (v);
- return (*this);
- }
- public:
- // lambda 表达式会到这里
- // Binder (bind 结果) 会到这里
- template <typename TX>
- // inline void Push (const TX & handler)
- inline void Push (const _Key K, TX handler)
- {
- m_handlers.emplace (K, std::move (handler));
- }
- // 静态函数会到这里
- inline void Push (const _Key K, _Ret (*fn) (Args...))
- {
- m_handlers.emplace (K, std::move (fn));
- }
- #if 1
- // 类的成员函数会到这里 - 3 个
- // 这里用了个小技巧: 把类实例和成员函数转换成一个临时的 lambda 函数
- // 另外, 不管 _Ret 是否为 void, 下面的代码都能通过编译 ! 暂不清楚 C++ 编译器是如何区分的 !
- template <typename TC>
- inline void Push (const _Key K, TC * inst, _Ret (TC::* mfn) (Args...))
- {
- m_handlers.emplace (K, [inst, mfn] (Args... args) { return (*inst.*mfn) (args...); });
- }
- template <typename TC>
- void Push (const _Key K, TC * inst, _Ret (TC::* mfn) (Args...) const)
- {
- m_handlers.emplace (K, [inst, mfn] (Args... args) { return (*inst.*mfn) (args...); });
- }
- template<typename TC>
- void Push (const _Key K, const TC * inst, _Ret (TC::* mfn) (Args...) const)
- {
- m_handlers.emplace (K, [inst, mfn] (Args... args) {return (*inst.*mfn) (args...); });
- }
- #endif
- };
- }
|