亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中事件機制的簡潔實現及需要放棄的特性

2020-01-26 16:22:18
字體:
來源:轉載
供稿:網友
事件模型是被廣泛使用的好東西,但是C++標準庫里沒有現成的,其他實現又復雜或者不優雅,比如需要使用宏?,F在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進設施組合出一個輕便的實現吧。

為了達到簡潔的目的,需要放棄一些特性
1、不支持判斷函數是否已經綁定過(因為std::function不提供比較方法,自己實現function的話代碼又變多了)
2、需要使用者接收返回的回調函數標識來移除事件綁定(原因同上)
3、事件沒有返回值,不支持回調函數優先級、條件回調等事件高級特性(比如返回所有處理結果中的最大最小值;只回調與指定參數匹配的事件處理函數)
4、事件參數理論上無限,實際上有限,一般支持0~10個參數(VC11還沒有支持變長模板參數,GCC有了。不過可以通過缺省模板參數和偏特化來模擬,所以理論上無限制)
5、不是線程安全的

:3、5兩條可以通過引入策略模式來提供靈活支持,就像標準庫和Loki做的那樣,實現一個完整的事件機制。

最簡單的實現
復制代碼 代碼如下:

#include <map>
#include <functional>
using namespace std;
template<class Param1, class Param2>
class Event
{
typedef void HandlerT(Param1, Param2);
int m_handlerId;
public:
Event() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
void operator ()(Param1 arg1, Param2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
private:
map<int, function<HandlerT>> m_handlers;
};

addHandler把回調函數完美轉發給std::function,讓標準庫來搞定各種重載,然后返回一個標識符用來注銷綁定。試一下,工作的不錯:
復制代碼 代碼如下:

void f1(int, int)
{
puts("f1()");
}
struct F2
{
void f(int, int)
{
puts("f2()");
}
void operator ()(int, int)
{
puts("f3()");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Event<int, int> e;
int id = e.addHandler(f1);
e.removeHandler(id);
using namespace std::placeholders;
F2 f2;
e.addHandler(bind(&F2::f, f2, _1, _2));
e.addHandler(bind(f2, _1, _2));
e.addHandler([](int, int) {
puts("f4()");
});
e(1, 2);
return 0;
}

雖然這里有一個小小的缺點,對于仿函數,如果想使用它的指針或引用是不可以直接綁定的,需要這樣做:
復制代碼 代碼如下:

e.addHandler(ref(f2));
e.addHandler(ref(*pf2)); // pf2是指向f2的指針 但是使用仿函數對象指針的情形不多,也不差多敲幾個

字符,何況在有Lambda表達式的情況下呢?
改進
1、有人不喜歡bind,用起來麻煩,放到addhandler里面去:
復制代碼 代碼如下:

template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}

2、擴展參數個數。沒有變長模板參數,變通一下:
復制代碼 代碼如下:

struct NullType {};
template<class P1 = Private::NullType, class P2 = Private::NullType>
class Event
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<>
class Event<Private::NullType, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj)));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType>
{
public:
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};

現在支持0~2個參數了。注意到各個模板里有公共代碼,提取出來放進基類,然后要做的就是打開文本生成器了
完整代碼
代碼下載
復制代碼 代碼如下:

View Code
#pragma once
#include <map>
#include <functional>
namespace Utility
{
namespace Private
{
struct NullType {};
template<class HandlerT>
class EventBase
{
public:
EventBase() : m_handlerId(0) {}
template<class FuncT> int addHandler(FuncT func)
{
m_handlers.emplace(m_handlerId, std::forward<FuncT>(func));
return m_handlerId++;
}
void removeHandler(int handlerId)
{
m_handlers.erase(handlerId);
}
protected:
int m_handlerId;
std::map<int, std::function<HandlerT>> m_handlers;
};
}
template<class P1 = Private::NullType, class P2 = Private::NullType, class P3 = Private::NullType, class P4 = Private::NullType, class P5 = Private::NullType, class P6 = Private::NullType, class P7 = Private::NullType, class P8 = Private::NullType, class P9 = Private::NullType, class P10 = Private::NullType>
class Event
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9, _10));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9, P10 arg10)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}
};
template<>
class Event<Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void ()>
{
public:
using Private::EventBase<void ()>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT const obj, FuncT func)
{
m_handlers.emplace(m_handlerId, std::bind(func, obj));
return m_handlerId++;
}
void operator ()()
{
for ( const auto& i : m_handlers )
i.second();
}
};
template<class P1>
class Event<P1, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1)>
{
public:
using Private::EventBase<void (P1)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1));
return m_handlerId++;
}
void operator ()(P1 arg1)
{
for ( const auto& i : m_handlers )
i.second(arg1);
}
};
template<class P1, class P2>
class Event<P1, P2, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2)>
{
public:
using Private::EventBase<void (P1, P2)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2);
}
};
template<class P1, class P2, class P3>
class Event<P1, P2, P3, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3)>
{
public:
using Private::EventBase<void (P1, P2, P3)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3);
}
};
template<class P1, class P2, class P3, class P4>
class Event<P1, P2, P3, P4, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4);
}
};
template<class P1, class P2, class P3, class P4, class P5>
class Event<P1, P2, P3, P4, P5, Private::NullType, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6>
class Event<P1, P2, P3, P4, P5, P6, Private::NullType, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
class Event<P1, P2, P3, P4, P5, P6, P7, Private::NullType, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, Private::NullType, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
};
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
class Event<P1, P2, P3, P4, P5, P6, P7, P8, P9, Private::NullType>
: public Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>
{
public:
using Private::EventBase<void (P1, P2, P3, P4, P5, P6, P7, P8, P9)>::addHandler;
template<class ObjT, class FuncT> int addHandler(ObjT obj, FuncT func)
{
using namespace std::placeholders;
m_handlers.emplace(m_handlerId, std::bind(func, std::forward<ObjT>(obj), _1, _2, _3, _4, _5, _6, _7, _8, _9));
return m_handlerId++;
}
void operator ()(P1 arg1, P2 arg2, P3 arg3, P4 arg4, P5 arg5, P6 arg6, P7 arg7, P8 arg8, P9 arg9)
{
for ( const auto& i : m_handlers )
i.second(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
};
} // namespace Utility

測試代碼
各種綁定方式
復制代碼 代碼如下:

View Code
#include "Event.h"
using namespace std;
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<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;
}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
www.久久撸.com| 国产视频福利一区| 久久人人爽人人爽人人片亚洲| 国产精品美女www爽爽爽视频| 日韩欧美在线一区| 91精品国产色综合久久不卡98口| 色阁综合伊人av| 久久久久久亚洲精品中文字幕| 精品久久久久久久久久ntr影视| 国产精品一区电影| 亚洲欧美日韩在线一区| 欧美在线视频一区二区| 国产女人精品视频| 久久成人国产精品| 国产精品99久久久久久人| 美女视频黄免费的亚洲男人天堂| 日本久久久久亚洲中字幕| 78m国产成人精品视频| 欧美黑人巨大精品一区二区| 色综合久久久久久中文网| 欧美资源在线观看| 国产精品美腿一区在线看| 疯狂做受xxxx高潮欧美日本| 亚洲www视频| 色av吧综合网| 久久中文精品视频| 91亚洲一区精品| 国产aaa精品| 久久99久久99精品免观看粉嫩| 日韩成人在线视频网站| 中文字幕免费国产精品| 92版电视剧仙鹤神针在线观看| 在线观看国产成人av片| 清纯唯美日韩制服另类| 亚洲国产91色在线| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲v日韩v综合v精品v| 永久555www成人免费| 最近2019免费中文字幕视频三| 久久99精品久久久久久噜噜| 国产国语刺激对白av不卡| 国产精品91在线| 亚洲国内精品视频| 亚洲欧美精品伊人久久| 国产欧美精品日韩| 亚洲伊人久久综合| 伊人久久免费视频| 欧美国产日韩中文字幕在线| 欧美超级免费视 在线| 98精品国产自产在线观看| 97超碰国产精品女人人人爽| 亚洲级视频在线观看免费1级| 日韩久久免费视频| 在线观看国产成人av片| 欧美一级免费视频| 亚洲精品国产精品国自产观看浪潮| 亚洲国产成人av在线| 精品国产乱码久久久久久天美| 日韩av中文字幕在线免费观看| 国产成人精品av在线| 欧美成人午夜激情| 操人视频在线观看欧美| 国产精品久久久久久久久借妻| 中文字幕日韩欧美在线视频| 国产精品日韩欧美大师| 成人h猎奇视频网站| 国产精品v片在线观看不卡| 精品亚洲夜色av98在线观看| 国内自拍欧美激情| 国产成人啪精品视频免费网| 国产日韩精品电影| 国产一区二区日韩精品欧美精品| 九九九久久国产免费| 中文字幕久久亚洲| 国内精品久久久| 久99久在线视频| 久久精品视频亚洲| 精品中文字幕久久久久久| 九九综合九九综合| 亚洲免费视频观看| 国产日韩视频在线观看| 日韩一区在线视频| 欧美老女人www| 日韩高清av一区二区三区| 日本三级久久久| 亚洲精品美女网站| 久久国产精品免费视频| www.久久久久| 国产精品日韩在线一区| 国产97在线观看| 欧美天堂在线观看| 激情懂色av一区av二区av| 日韩久久精品成人| 亚洲欧美国产制服动漫| 国产视频精品自拍| 亚州成人av在线| 欧美日韩第一页| 亚洲精品久久久久久久久久久久久| 日韩av影院在线观看| 久久国产天堂福利天堂| 91免费看国产| 欧美最猛性xxxxx(亚洲精品)| 一区二区av在线| 国产亚洲精品一区二555| 精品久久久久久久久中文字幕| 欧洲日本亚洲国产区| 欧美性感美女h网站在线观看免费| 久99久在线视频| 国语自产在线不卡| 久久久久亚洲精品成人网小说| 精品国产一区av| 日韩欧美国产一区二区| 另类美女黄大片| 欧美韩国理论所午夜片917电影| 国产+人+亚洲| 欧美电影免费观看| 日本三级韩国三级久久| 国产aⅴ夜夜欢一区二区三区| 茄子视频成人在线| 亚洲aaaaaa| 国产精品亚洲激情| 26uuu另类亚洲欧美日本一| 国产成人精品一区| 中文字幕一区二区精品| 亚洲电影免费观看高清| 欧美性xxxx极品hd欧美风情| 久久99国产精品久久久久久久久| 久久久久999| 久久精品国产清自在天天线| 97av在线影院| 久久久久久国产精品美女| 久久99久久99精品免观看粉嫩| 欧美性做爰毛片| 久热在线中文字幕色999舞| 久久影视免费观看| 96sao精品视频在线观看| 国产有码一区二区| 欧美亚洲免费电影| 国产美女精品视频免费观看| 91精品久久久久久久久久入口| 欧美性猛交xxxx免费看漫画| www.亚洲一区| 亚洲影院色在线观看免费| 国产日韩欧美一二三区| 成人欧美一区二区三区黑人| 国产成人精品综合| 精品久久久久久中文字幕一区奶水| 精品亚洲夜色av98在线观看| 日韩美女免费视频| 国产精品第3页| 91精品久久久久久久| 欧美激情影音先锋| 成人av番号网| 亚洲精品国产免费| 国产人妖伪娘一区91| 欧美日韩美女在线| 在线电影欧美日韩一区二区私密| 亚洲天堂精品在线| 91香蕉亚洲精品| 亚洲精品理论电影| 欧美做受高潮电影o| 麻豆国产va免费精品高清在线| 中文字幕亚洲一区二区三区五十路| 欧美中文在线观看国产|