虽然这里有一个小小的缺点,对于仿函数,如果想使用它的指针或引用是不可以直接绑定的,需要这样做:

1 e.addHandler(ref(f2));
2 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个参数了。注意到各个模板里有公共代码,提取出来放进基类,然后要做的是打开文本生成器了

  补充一下:VC里std::function默认多5个参数,多支持10个,要在编译开关里设置一下宏_VARIADIC_MAX=10