fw: refactor Strategy registry

Strategy registry is moved into Strategy class.
Strategy instantiation logic is implemented in Strategy::create.
These are in preparation of supporting Strategy parameters.

refs #3868

Change-Id: If36a08ad25a00a7008a5eccc8cfe4f6c63638676
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index f4ef3b1..0bc8d9e 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FW_STRATEGY_HPP
 
 #include "forwarder.hpp"
-#include "strategy-registry.hpp"
 #include "table/measurements-accessor.hpp"
 
 namespace nfd {
@@ -35,9 +34,47 @@
 
 /** \brief represents a forwarding strategy
  */
-class Strategy : public enable_shared_from_this<Strategy>, noncopyable
+class Strategy : noncopyable
 {
-public:
+public: // registry
+  /** \brief register a strategy type
+   *  \tparam S subclass of Strategy
+   *  \param strategyName versioned strategy name
+   *  \note It is permitted to register the same strategy type under multiple names,
+   *        which is useful in tests and for creating aliases.
+   */
+  template<typename S>
+  static void
+  registerType(const Name& strategyName = S::STRATEGY_NAME)
+  {
+    Registry& registry = getRegistry();
+    BOOST_ASSERT(registry.count(strategyName) == 0);
+    registry[strategyName] = &make_unique<S, Forwarder&, const Name&>;
+  }
+
+  /** \return whether a strategy instance can be created from \p strategyName
+   *  \param strategyName strategy name, may contain version
+   *  \todo #3868 may contain parameters
+   *  \note This function finds a strategy type using same rules as \p create ,
+   *        but does not attempt to construct an instance.
+   */
+  static bool
+  canCreate(const Name& strategyName);
+
+  /** \return a strategy instance created from \p strategyName,
+   *  \retval nullptr if !canCreate(strategyName)
+   *  \todo #3868 throw std::invalid_argument strategy type constructor
+   *              does not accept specified version or parameters
+   */
+  static unique_ptr<Strategy>
+  create(const Name& strategyName, Forwarder& forwarder);
+
+  /** \return registered versioned strategy names
+   */
+  static std::set<Name>
+  listRegistered();
+
+public: // constructor, destructor, strategy name
   /** \brief construct a strategy instance
    *  \param forwarder a reference to the Forwarder, used to enable actions and accessors.
    *         Strategy subclasses should pass this reference,
@@ -205,7 +242,17 @@
   signal::Signal<FaceTable, Face&>& afterAddFace;
   signal::Signal<FaceTable, Face&>& beforeRemoveFace;
 
-private:
+private: // registry
+  typedef std::function<unique_ptr<Strategy>(Forwarder& forwarder, const Name& strategyName)> CreateFunc;
+  typedef std::map<Name, CreateFunc> Registry; // indexed by strategy name
+
+  static Registry&
+  getRegistry();
+
+  static Registry::const_iterator
+  find(const Name& strategyName);
+
+private: // instance fields
   Name m_name;
 
   /** \brief reference to the forwarder
@@ -220,4 +267,18 @@
 } // namespace fw
 } // namespace nfd
 
+/** \brief registers a strategy
+ *
+ *  This macro should appear once in .cpp of each strategy.
+ */
+#define NFD_REGISTER_STRATEGY(S)                       \
+static class NfdAuto ## S ## StrategyRegistrationClass \
+{                                                      \
+public:                                                \
+  NfdAuto ## S ## StrategyRegistrationClass()          \
+  {                                                    \
+    ::nfd::fw::Strategy::registerType<S>();            \
+  }                                                    \
+} g_nfdAuto ## S ## StrategyRegistrationVariable
+
 #endif // NFD_DAEMON_FW_STRATEGY_HPP