C++中事件機(jī)制的簡(jiǎn)潔實(shí)現(xiàn)及需要放棄的特性
更新時(shí)間:2013年02月01日 14:54:38 作者:
事件模型是被廣泛使用的好東西,但是C++標(biāo)準(zhǔn)庫(kù)里沒(méi)有現(xiàn)成的,現(xiàn)在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進(jìn)設(shè)施組合出一個(gè)輕便的實(shí)現(xiàn)吧感興趣的朋友可以了解下,或許對(duì)你有所幫助
事件模型是被廣泛使用的好東西,但是C++標(biāo)準(zhǔn)庫(kù)里沒(méi)有現(xiàn)成的,其他實(shí)現(xiàn)又復(fù)雜或者不優(yōu)雅,比如需要使用宏。現(xiàn)在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先進(jìn)設(shè)施組合出一個(gè)輕便的實(shí)現(xiàn)吧。
為了達(dá)到簡(jiǎn)潔的目的,需要放棄一些特性:
1、不支持判斷函數(shù)是否已經(jīng)綁定過(guò)(因?yàn)閟td::function不提供比較方法,自己實(shí)現(xiàn)function的話代碼又變多了)
2、需要使用者接收返回的回調(diào)函數(shù)標(biāo)識(shí)來(lái)移除事件綁定(原因同上)
3、事件沒(méi)有返回值,不支持回調(diào)函數(shù)優(yōu)先級(jí)、條件回調(diào)等事件高級(jí)特性(比如返回所有處理結(jié)果中的最大最小值;只回調(diào)與指定參數(shù)匹配的事件處理函數(shù))
4、事件參數(shù)理論上無(wú)限,實(shí)際上有限,一般支持0~10個(gè)參數(shù)(VC11還沒(méi)有支持變長(zhǎng)模板參數(shù),GCC有了。不過(guò)可以通過(guò)缺省模板參數(shù)和偏特化來(lái)模擬,所以理論上無(wú)限制)
5、不是線程安全的
注:3、5兩條可以通過(guò)引入策略模式來(lái)提供靈活支持,就像標(biāo)準(zhǔn)庫(kù)和Loki做的那樣,實(shí)現(xiàn)一個(gè)完整的事件機(jī)制。
最簡(jiǎn)單的實(shí)現(xiàn)
#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把回調(diào)函數(shù)完美轉(zhuǎn)發(fā)給std::function,讓標(biāo)準(zhǔn)庫(kù)來(lái)搞定各種重載,然后返回一個(gè)標(biāo)識(shí)符用來(lái)注銷綁定。試一下,工作的不錯(cuò):
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;
}
雖然這里有一個(gè)小小的缺點(diǎn),對(duì)于仿函數(shù),如果想使用它的指針或引用是不可以直接綁定的,需要這樣做:
e.addHandler(ref(f2));
e.addHandler(ref(*pf2)); // pf2是指向f2的指針 但是使用仿函數(shù)對(duì)象指針的情形不多,也不差多敲幾個(gè)
字符,何況在有Lambda表達(dá)式的情況下呢?
改進(jìn)
1、有人不喜歡bind,用起來(lái)麻煩,放到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、擴(kuò)展參數(shù)個(gè)數(shù)。沒(méi)有變長(zhǎng)模板參數(shù),變通一下:
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);
}
};
現(xiàn)在支持0~2個(gè)參數(shù)了。注意到各個(gè)模板里有公共代碼,提取出來(lái)放進(jìn)基類,然后要做的就是打開(kāi)文本生成器了
完整代碼
代碼下載
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
測(cè)試代碼
各種綁定方式
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;
// 一般函數(shù)
e.addHandler(f1);
int id = e.addHandler(&f1);
e.removeHandler(id); // 移除事件處理函數(shù)
// 成員函數(shù)
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); // 對(duì)象拷貝構(gòu)造
puts("----addHandler(F2(), &F2::f)----");
e.addHandler(F2(), &F2::f); // 對(duì)象轉(zhuǎn)移構(gòu)造
puts("--------");
// 仿函數(shù)
F3 f3;
const F3 *pf3 = &f3;
puts("----addHandler(f3)----");
e.addHandler(f3); // 對(duì)象拷貝構(gòu)造
puts("----addHandler(F3())----");
e.addHandler(F3()); // 對(duì)象轉(zhuǎn)移構(gòu)造
puts("--------");
e.addHandler(ref(f3)); // 引用仿函數(shù)對(duì)象
e.addHandler(ref(*pf3)); // 引用仿函數(shù)常量對(duì)象
puts("--------");
// Lambda表達(dá)式
e.addHandler([](int, int) {
puts("f4()");
});
// 激發(fā)事件
e(1, 2);
return 0;
}
為了達(dá)到簡(jiǎn)潔的目的,需要放棄一些特性:
1、不支持判斷函數(shù)是否已經(jīng)綁定過(guò)(因?yàn)閟td::function不提供比較方法,自己實(shí)現(xiàn)function的話代碼又變多了)
2、需要使用者接收返回的回調(diào)函數(shù)標(biāo)識(shí)來(lái)移除事件綁定(原因同上)
3、事件沒(méi)有返回值,不支持回調(diào)函數(shù)優(yōu)先級(jí)、條件回調(diào)等事件高級(jí)特性(比如返回所有處理結(jié)果中的最大最小值;只回調(diào)與指定參數(shù)匹配的事件處理函數(shù))
4、事件參數(shù)理論上無(wú)限,實(shí)際上有限,一般支持0~10個(gè)參數(shù)(VC11還沒(méi)有支持變長(zhǎng)模板參數(shù),GCC有了。不過(guò)可以通過(guò)缺省模板參數(shù)和偏特化來(lái)模擬,所以理論上無(wú)限制)
5、不是線程安全的
注:3、5兩條可以通過(guò)引入策略模式來(lái)提供靈活支持,就像標(biāo)準(zhǔn)庫(kù)和Loki做的那樣,實(shí)現(xiàn)一個(gè)完整的事件機(jī)制。
最簡(jiǎn)單的實(shí)現(xiàn)
復(fù)制代碼 代碼如下:
#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把回調(diào)函數(shù)完美轉(zhuǎn)發(fā)給std::function,讓標(biāo)準(zhǔn)庫(kù)來(lái)搞定各種重載,然后返回一個(gè)標(biāo)識(shí)符用來(lái)注銷綁定。試一下,工作的不錯(cuò):
復(fù)制代碼 代碼如下:
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;
}
雖然這里有一個(gè)小小的缺點(diǎn),對(duì)于仿函數(shù),如果想使用它的指針或引用是不可以直接綁定的,需要這樣做:
復(fù)制代碼 代碼如下:
e.addHandler(ref(f2));
e.addHandler(ref(*pf2)); // pf2是指向f2的指針 但是使用仿函數(shù)對(duì)象指針的情形不多,也不差多敲幾個(gè)
字符,何況在有Lambda表達(dá)式的情況下呢?
改進(jìn)
1、有人不喜歡bind,用起來(lái)麻煩,放到addhandler里面去:
復(fù)制代碼 代碼如下:
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、擴(kuò)展參數(shù)個(gè)數(shù)。沒(méi)有變長(zhǎng)模板參數(shù),變通一下:
復(fù)制代碼 代碼如下:
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);
}
};
現(xiàn)在支持0~2個(gè)參數(shù)了。注意到各個(gè)模板里有公共代碼,提取出來(lái)放進(jìn)基類,然后要做的就是打開(kāi)文本生成器了
完整代碼
代碼下載
復(fù)制代碼 代碼如下:
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
測(cè)試代碼
各種綁定方式
復(fù)制代碼 代碼如下:
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;
// 一般函數(shù)
e.addHandler(f1);
int id = e.addHandler(&f1);
e.removeHandler(id); // 移除事件處理函數(shù)
// 成員函數(shù)
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); // 對(duì)象拷貝構(gòu)造
puts("----addHandler(F2(), &F2::f)----");
e.addHandler(F2(), &F2::f); // 對(duì)象轉(zhuǎn)移構(gòu)造
puts("--------");
// 仿函數(shù)
F3 f3;
const F3 *pf3 = &f3;
puts("----addHandler(f3)----");
e.addHandler(f3); // 對(duì)象拷貝構(gòu)造
puts("----addHandler(F3())----");
e.addHandler(F3()); // 對(duì)象轉(zhuǎn)移構(gòu)造
puts("--------");
e.addHandler(ref(f3)); // 引用仿函數(shù)對(duì)象
e.addHandler(ref(*pf3)); // 引用仿函數(shù)常量對(duì)象
puts("--------");
// Lambda表達(dá)式
e.addHandler([](int, int) {
puts("f4()");
});
// 激發(fā)事件
e(1, 2);
return 0;
}
您可能感興趣的文章:
- VC++實(shí)現(xiàn)文件與應(yīng)用程序關(guān)聯(lián)的方法(注冊(cè)表修改)
- C++寫(xiě)注冊(cè)表項(xiàng)實(shí)例
- C++訪問(wèn)注冊(cè)表獲取已安裝軟件信息列表示例代碼
- C++設(shè)置事件通知線程工作的方法
- 解決C++中事件不響應(yīng)的方法詳解
- C++事件處理中__event與__raise關(guān)鍵字的用法講解
- 深入解析C++程序中激發(fā)事件和COM中的事件處理
- C++事件處理中的__hook與__unhook用法詳解
- C++事件驅(qū)動(dòng)型銀行排隊(duì)模擬
- VC++實(shí)現(xiàn)添加文件關(guān)聯(lián)的方法示例
相關(guān)文章
解析Linux下的時(shí)間函數(shù):設(shè)置以及獲取時(shí)間的方法
本篇文章是對(duì)Linux下的時(shí)間函數(shù):設(shè)置以及獲取時(shí)間的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)圖的創(chuàng)建與遍歷實(shí)驗(yàn)示例
這篇文章主要為大家介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)圖的創(chuàng)建與遍歷實(shí)驗(yàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06C數(shù)據(jù)結(jié)構(gòu)之單鏈表詳細(xì)示例分析
以下是對(duì)C語(yǔ)言中的單鏈表進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下2013-08-08C語(yǔ)言使用realloc函數(shù)實(shí)現(xiàn)通訊錄源碼分析
什么是動(dòng)態(tài)通訊錄,就是在靜態(tài)的基礎(chǔ)上改進(jìn)了一下,不在使用數(shù)組,而是使用指針和動(dòng)態(tài)內(nèi)存開(kāi)辟的函數(shù),當(dāng)空間不夠的時(shí)候,便進(jìn)行增容2023-02-02C++判斷一個(gè)點(diǎn)是否在圓內(nèi)的方法
這篇文章主要為大家詳細(xì)介紹了C++判斷一個(gè)點(diǎn)是否在圓內(nèi)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05QT5實(shí)現(xiàn)簡(jiǎn)單的TCP通信的實(shí)現(xiàn)
本文主要介紹了QT5實(shí)現(xiàn)簡(jiǎn)單的TCP通信的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05