标签:
才想起来像这样“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
标签:
原文地址:http://www.cnblogs.com/shouce/p/5229601.html