util: rewrite EventEmitter with C++11 features

This commit does not enhance the functionality of EventEmitter.

refs #2116

Change-Id: Iff1d5ae9fbd8e575773d71c7a93339045fcb8bc4
diff --git a/src/util/event-emitter.hpp b/src/util/event-emitter.hpp
index d43bd24..261dabc 100644
--- a/src/util/event-emitter.hpp
+++ b/src/util/event-emitter.hpp
@@ -17,33 +17,7 @@
  * <http://www.gnu.org/licenses/>.
  *
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * This code is actually copied from NFD project (NDN Forwarding Daemon).
- * We acknowledge the permission of the authors of NFD.
  */
-/**
- * Copyright (c) 2014  Regents of the University of California,
- *                     Arizona Board of Regents,
- *                     Colorado State University,
- *                     University Pierre & Marie Curie, Sorbonne University,
- *                     Washington University in St. Louis,
- *                     Beijing Institute of Technology
- *
- * This file is part of NFD (Named Data Networking Forwarding Daemon).
- * See AUTHORS.md for complete list of NFD authors and contributors.
- *
- * NFD is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
 
 #ifndef NDN_UTIL_EVENT_EMITTER_HPP
 #define NDN_UTIL_EVENT_EMITTER_HPP
@@ -54,12 +28,7 @@
 namespace ndn {
 namespace util {
 
-struct empty
-{
-};
-
-/** \class EventEmitter
- *  \brief provides a lightweight event system
+/** \brief provides a lightweight event system
  *
  *  To declare an event:
  *    EventEmitter<TArgs> onEventName;
@@ -72,303 +41,65 @@
  *    onEventName.clear();
  */
 
-// four arguments
-template<typename T1 = empty, typename T2 = empty,
-         typename T3 = empty, typename T4 = empty>
+template<typename ...TArgs>
 class EventEmitter : noncopyable
 {
 public:
-  /// represents a handler that can subscribe to the event
-  typedef function<void(const T1&, const T2&,
-                        const T3&, const T4&)> Handler;
+  /** \brief represents a handler that can subscribe to the event
+   */
+  typedef function<void(const TArgs&...)> Handler;
 
-  /// adds an subscription
+  /** \brief subscribes to the event
+   */
   void
-  operator+=(Handler handler);
+  operator+=(const Handler& handler);
 
-  /// returns true if there is no subscription,
-  /// otherwise returns false
+  /** \return true if there is no subscription, false otherwise
+   */
   bool
   isEmpty() const;
 
-  /// clears all subscriptions
+  /** \brief clears all subscriptions
+   */
   void
   clear();
 
-  /// triggers the event
+  /** \brief triggers the event
+   */
   void
-  operator()(const T1& a1, const T2& a2, const T3& a3, const T4& a4);
-
-private:
-  /// stores all subscribed handlers
-  std::vector<Handler> m_handlers;
-};
-
-// zero argument
-template<>
-class EventEmitter<empty, empty, empty, empty> : noncopyable
-{
-public:
-  typedef function<void()> Handler;
-
-  void
-  operator+=(Handler handler);
-
-  bool
-  isEmpty() const;
-
-  void
-  clear();
-
-  void
-  operator()();
+  operator()(const TArgs&...args) const;
 
 private:
   std::vector<Handler> m_handlers;
 };
 
-
-// one argument
-template<typename T1>
-class EventEmitter<T1, empty, empty, empty> : noncopyable
-{
-public:
-  typedef function<void(const T1&)> Handler;
-
-  void
-  operator+=(Handler handler);
-
-  bool
-  isEmpty() const;
-
-  void
-  clear();
-
-  void
-  operator()(const T1& a1);
-
-private:
-  std::vector<Handler> m_handlers;
-};
-
-
-// two arguments
-template<typename T1, typename T2>
-class EventEmitter<T1, T2, empty, empty> : noncopyable
-{
-public:
-  typedef function<void(const T1&, const T2&)> Handler;
-
-  void
-  operator+=(Handler handler);
-
-  bool
-  isEmpty() const;
-
-  void
-  clear();
-
-  void
-  operator()(const T1& a1, const T2& a2);
-
-private:
-  std::vector<Handler> m_handlers;
-};
-
-
-// three arguments
-template<typename T1, typename T2, typename T3>
-class EventEmitter<T1, T2, T3, empty> : noncopyable
-{
-public:
-  typedef function<void(const T1&, const T2&, const T3&)> Handler;
-
-  void
-  operator+=(Handler handler);
-
-  bool
-  isEmpty() const;
-
-  void
-  clear();
-
-  void
-  operator()(const T1& a1, const T2& a2, const T3& a3);
-
-private:
-  std::vector<Handler> m_handlers;
-};
-
-
-// zero argument
-
+template<typename ...TArgs>
 inline void
-EventEmitter<empty, empty, empty, empty>::operator+=(Handler handler)
+EventEmitter<TArgs...>::operator+=(const Handler& handler)
 {
   m_handlers.push_back(handler);
 }
 
+template<typename ...TArgs>
 inline bool
-EventEmitter<empty, empty, empty, empty>::isEmpty() const
+EventEmitter<TArgs...>::isEmpty() const
 {
   return m_handlers.empty();
 }
 
+template<typename ...TArgs>
 inline void
-EventEmitter<empty, empty, empty, empty>::clear()
+EventEmitter<TArgs...>::clear()
 {
   return m_handlers.clear();
 }
 
+template<typename ...TArgs>
 inline void
-EventEmitter<empty, empty, empty, empty>::operator()()
+EventEmitter<TArgs...>::operator()(const TArgs&...args) const
 {
-  std::vector<Handler>::iterator it;
-  for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
-    (*it)();
-    if (m_handlers.empty()) // .clear has been called
-      return;
-  }
-}
-
-// one argument
-
-template<typename T1>
-inline void
-EventEmitter<T1, empty, empty, empty>::operator+=(Handler handler)
-{
-  m_handlers.push_back(handler);
-}
-
-template<typename T1>
-inline bool
-EventEmitter<T1, empty, empty, empty>::isEmpty() const
-{
-  return m_handlers.empty();
-}
-
-template<typename T1>
-inline void
-EventEmitter<T1, empty, empty, empty>::clear()
-{
-  return m_handlers.clear();
-}
-
-template<typename T1>
-inline void
-EventEmitter<T1, empty, empty, empty>::operator()(const T1& a1)
-{
-  typename std::vector<Handler>::iterator it;
-  for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
-    (*it)(a1);
-    if (m_handlers.empty()) // .clear has been called
-      return;
-  }
-}
-
-// two arguments
-
-template<typename T1, typename T2>
-inline void
-EventEmitter<T1, T2, empty, empty>::operator+=(Handler handler)
-{
-  m_handlers.push_back(handler);
-}
-
-template<typename T1, typename T2>
-inline bool
-EventEmitter<T1, T2, empty, empty>::isEmpty() const
-{
-  return m_handlers.empty();
-}
-
-template<typename T1, typename T2>
-inline void
-EventEmitter<T1, T2, empty, empty>::clear()
-{
-  return m_handlers.clear();
-}
-
-template<typename T1, typename T2>
-inline void
-EventEmitter<T1, T2, empty, empty>::operator()
-    (const T1& a1, const T2& a2)
-{
-  typename std::vector<Handler>::iterator it;
-  for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
-    (*it)(a1, a2);
-    if (m_handlers.empty()) // .clear has been called
-      return;
-  }
-}
-
-// three arguments
-
-template<typename T1, typename T2, typename T3>
-inline void
-EventEmitter<T1, T2, T3, empty>::operator+=(Handler handler)
-{
-  m_handlers.push_back(handler);
-}
-
-template<typename T1, typename T2, typename T3>
-inline bool
-EventEmitter<T1, T2, T3, empty>::isEmpty() const
-{
-  return m_handlers.empty();
-}
-
-template<typename T1, typename T2, typename T3>
-inline void
-EventEmitter<T1, T2, T3, empty>::clear()
-{
-  return m_handlers.clear();
-}
-
-template<typename T1, typename T2, typename T3>
-inline void
-EventEmitter<T1, T2, T3, empty>::operator()
-    (const T1& a1, const T2& a2, const T3& a3)
-{
-  typename std::vector<Handler>::iterator it;
-  for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
-    (*it)(a1, a2, a3);
-    if (m_handlers.empty()) // .clear has been called
-      return;
-  }
-}
-
-// four arguments
-
-template<typename T1, typename T2, typename T3, typename T4>
-inline void
-EventEmitter<T1, T2, T3, T4>::operator+=(Handler handler)
-{
-  m_handlers.push_back(handler);
-}
-
-template<typename T1, typename T2, typename T3, typename T4>
-inline bool
-EventEmitter<T1, T2, T3, T4>::isEmpty() const
-{
-  return m_handlers.empty();
-}
-
-template<typename T1, typename T2, typename T3, typename T4>
-inline void
-EventEmitter<T1, T2, T3, T4>::clear()
-{
-  return m_handlers.clear();
-}
-
-template<typename T1, typename T2, typename T3, typename T4>
-inline void
-EventEmitter<T1, T2, T3, T4>::operator()
-    (const T1& a1, const T2& a2, const T3& a3, const T4& a4)
-{
-  typename std::vector<Handler>::iterator it;
-  for (it = m_handlers.begin(); it != m_handlers.end(); ++it) {
-    (*it)(a1, a2, a3, a4);
+  for (const Handler& handler : m_handlers) {
+    handler(args...);
     if (m_handlers.empty()) // .clear has been called
       return;
   }