在我進入了答案,有些事情你應該知道:
隨着的是,除了,它需要大量的模板魔術和很多有趣的功能,基於函數指針和成員函數有回調,而不是僅僅使用std::function<>
。在我向您展示我最終使用的解決方案之前,我真誠地鼓勵您使用std::vector<std::function<[RETURNTYPE]([PARAMS])> >
(或者僅爲std::function
作爲單一回報),以免讓您嘗試完成所有工作的大量頭痛。無論如何,see my answer underneath @Insilico's for a Callback and Event system that works fine in GCC with variadic templates。
對於在VC++中工作的版本,正如我之前所說的那樣,您必須手動破解各種定義,最終創建一個Callback Class和一個Event類。它是多個回調,但可以簡化Event
類是單個連接/回調,如果你需要:
template<typename TFuncSignature>
class Callback;
/////////////////
/* 2 ARGUMENT */
/////////////////
template<typename R, typename T1, typename T2>
class Callback<R (T1, T2)> {
public:
typedef R (*TFunc)(void*, T1, T2);
const static size_t Arity = 2;
Callback() : obj(0), func(0) {}
Callback(void* o, TFunc f) : obj(o), func(f) {}
R operator()(T1 t1, T2 t2) const {
return (*func)(obj, t1, t2);
}
typedef void* Callback::*SafeBoolType;
operator SafeBoolType() const {
return func != 0? &Callback::obj : 0;
}
bool operator!() const {
return func == 0;
}
bool operator== (const Callback<R (T1, T2)>& right) const {
return obj == right.obj && func == right.func;
}
bool operator!= (const Callback<R (T1, T2)>& right) const {
return obj != right.obj || func != right.func;
}
private:
void* obj;
TFunc func;
};
namespace detail {
template<typename R, class T, typename T1, typename T2>
struct DeduceConstMemCallback2 {
template<R(T::*Func)(T1, T2) const> inline static Callback<R(T1, T2)> Bind(T* o) {
struct _ { static R wrapper(void* o, T1 t1, T2 t2) { return (static_cast<T*>(o)->*Func)(std::forward<T1>(t1, t2); } };
return Callback<R(T1, T2)>(o, (R(*)(void*, T1, T2)) _::wrapper);
}
};
template<typename R, class T, typename T1, typename T2>
struct DeduceMemCallback2 {
template<R(T::*Func)(T1, T2)> inline static Callback<R(T1, T2)> Bind(T* o) {
struct _ { static R wrapper(void* o, T1 t1, T2 t2) { return (static_cast<T*>(o)->*Func)(t1, t2)); } };
return Callback<R(T1, T2)>(o, (R(*)(void*, T1, T2)) _::wrapper);
}
};
template<typename R, typename T1, typename T2>
struct DeduceStaticCallback2 {
template<R(*Func)(T1, T2)> inline static Callback<R(T1, T2)> Bind() {
struct _ { static R wrapper(void*, T1 t1, T2 t2) { return (*Func)(t1), t2); } };
return Callback<R(T1, T2)>(0, (R(*)(void*, T1, T2)) _::wrapper);
}
};
}
template<typename R, class T, typename T1, typename T2>
detail::DeduceConstMemCallback2<R, T, T1, T2> DeduceCallback2(R(T::*)(T1, T2) const) {
return detail::DeduceConstMemCallback2<R, T, T1, T2>();
}
template<typename R, class T, typename T1, typename T2>
detail::DeduceMemCallback2<R, T, T1, T2> DeduceCallback2(R(T::*)(T1, T2)) {
return detail::DeduceMemCallback2<R, T, T1, T2>();
}
template<typename R, typename T1, typename T2>
detail::DeduceStaticCallback2<R, T1, T2> DeduceCallback2(R(*)(T1, T2)) {
return detail::DeduceStaticCallback2<R, T1, T2>();
}
template <typename T1, typename T2> class Event2 {
public:
typedef void(* TSignature)(T1, T2);
typedef Callback<void(T1, T2)> TCallback;
typedef std::vector<TCallback> InvocationTable;
protected:
InvocationTable invocations;
public:
const static int ExpectedFunctorCount = 2;
Event2() : invocations() {
invocations.reserve(ExpectedFunctorCount);
}
Event2 (int expectedfunctorcount) : invocations() {
invocations.reserve(expectedfunctorcount);
}
template <void (* TFunc)(T1, T2)> void Add () {
TCallback c = DeduceCallback2(TFunc).template Bind<TFunc>();
invocations.push_back(c);
}
template <typename T, void (T::* TFunc)(T1, T2)> void Add (T& object) {
Add<T, TFunc>(&object);
}
template <typename T, void (T::* TFunc)(T1, T2)> void Add (T* object) {
TCallback c = DeduceCallback2(TFunc).template Bind<TFunc>(object);
invocations.push_back(c);
}
template <typename T, void (T::* TFunc)(T1, T2) const> void Add (T& object) {
Add<T, TFunc>(&object);
}
template <typename T, void (T::* TFunc)(T1, T2) const> void Add (T* object) {
TCallback c = DeduceCallback2(TFunc).template Bind<TFunc>(object);
invocations.push_back(c);
}
void Invoke (T1 t1, T2 t2) {
size_t i;
for (i = 0; i < invocations.size(); ++i) {
invocations[i](t1, t2);
}
}
void operator() (T1 t1, T2 t2) {
size_t i;
for (i = 0; i < invocations.size(); ++i) {
invocations[i](t1, t2);
}
}
size_t InvocationCount () {
return invocations.size();
}
template <void (* TFunc)(T1, T2)> bool Remove()
{ return Remove (DeduceCallback2(TFunc).template Bind<TFunc>()); }
template <typename T, void (T::* TFunc)(T1, T2)> bool Remove (T& object)
{ return Remove <T, TFunc>(&object); }
template <typename T, void (T::* TFunc)(T1, T2)> bool Remove (T* object)
{ return Remove (DeduceCallback2(TFunc).template Bind<TFunc>(object)); }
template <typename T, void (T::* TFunc)(T1, T2) const> bool Remove (T& object)
{ return Remove <T, TFunc>(&object); }
template <typename T, void (T::* TFunc)(T1, T2) const> bool Remove (T* object)
{ return Remove (DeduceCallback2(TFunc).template Bind<TFunc>(object)); }
protected:
bool Remove(TCallback const& target) {
auto it = std::find(invocations.begin(), invocations.end(), target);
if (it == invocations.end())
return false;
invocations.erase(it);
return true;
}
};
'無效(*)($參數...)callbackPtr;'難道不該'void(* callbackPtr)($ arguments ...);'? – jrok 2013-02-22 20:30:39
嗯,如果我想添加多個在** std :: vector **中,如下所示:*** std :: vector處理程序; *** for多個事件處理程序?不知道命名在這種情況下如何工作。 –
2013-02-22 20:38:22
也許MSVS只是不接受'$'字符 – 2013-02-22 20:41:01