core: make SizeCounter use pointer instead of reference

Restore virtual inheritance of GenericLinkServiceCounters in
GenericLinkService

refs #3941

Change-Id: I368e4694fee7bc97173fddfc81d0c679da0d6eed
diff --git a/core/counter.hpp b/core/counter.hpp
index bb50c66..3a678ec 100644
--- a/core/counter.hpp
+++ b/core/counter.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -107,15 +107,17 @@
 
 /** \brief provides a counter that observes the size of a table
  *  \tparam T a type that provides a size() const member function
+ *
+ *  if table not specified in constructor, it can be added later by invoking observe()
  */
 template<typename T>
 class SizeCounter
 {
 public:
-  typedef size_t rep;
+  typedef size_t Rep;
 
-  constexpr
-  SizeCounter(const T& table)
+  explicit constexpr
+  SizeCounter(const T* table = nullptr)
     : m_table(table)
   {
   }
@@ -125,15 +127,22 @@
   SizeCounter&
   operator=(const SizeCounter&) = delete;
 
+  void
+  observe(const T* table)
+  {
+    m_table = table;
+  }
+
   /** \brief observe the counter
    */
-  operator rep() const
+  operator Rep() const
   {
-    return m_table.size();
+    BOOST_ASSERT(m_table != nullptr);
+    return m_table->size();
   }
 
 private:
-  const T& m_table;
+  const T* m_table;
 };
 
 } // namespace nfd
diff --git a/daemon/face/generic-link-service.cpp b/daemon/face/generic-link-service.cpp
index 9d1d0fc..20c1cb8 100644
--- a/daemon/face/generic-link-service.cpp
+++ b/daemon/face/generic-link-service.cpp
@@ -31,11 +31,6 @@
 
 NFD_LOG_INIT("GenericLinkService");
 
-GenericLinkServiceCounters::GenericLinkServiceCounters(const LpReassembler& reassembler)
-  : nReassembling(reassembler)
-{
-}
-
 GenericLinkService::Options::Options()
   : allowLocalFields(false)
   , allowFragmentation(false)
@@ -44,14 +39,14 @@
 }
 
 GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
-  : GenericLinkServiceCounters(m_reassembler)
-  , m_options(options)
+  : m_options(options)
   , m_fragmenter(m_options.fragmenterOptions, this)
   , m_reassembler(m_options.reassemblerOptions, this)
   , m_reliability(m_options.reliabilityOptions, this)
   , m_lastSeqNo(-2)
 {
   m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
+  nReassembling.observe(&m_reassembler);
 }
 
 void
diff --git a/daemon/face/generic-link-service.hpp b/daemon/face/generic-link-service.hpp
index 8a8622f..4c347d6 100644
--- a/daemon/face/generic-link-service.hpp
+++ b/daemon/face/generic-link-service.hpp
@@ -41,9 +41,6 @@
 class GenericLinkServiceCounters : public virtual LinkService::Counters
 {
 public:
-  explicit
-  GenericLinkServiceCounters(const LpReassembler& reassembler);
-
   /** \brief count of failed fragmentations
    */
   PacketCounter nFragmentationErrors;
@@ -87,10 +84,9 @@
 
 /** \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol
  *  \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
- *  \todo #3941 declare GenericLinkServiceCounters as virtual inheritance
  */
 class GenericLinkService : public LinkService
-                         , protected GenericLinkServiceCounters
+                         , protected virtual GenericLinkServiceCounters
 {
 public:
   /** \brief Options that control the behavior of GenericLinkService
diff --git a/tests/core/counter.t.cpp b/tests/core/counter.t.cpp
index 310e589..ce9a086 100644
--- a/tests/core/counter.t.cpp
+++ b/tests/core/counter.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -69,16 +69,22 @@
 BOOST_AUTO_TEST_CASE(SizeCnt)
 {
   std::vector<int> v;
-  SizeCounter<std::vector<int>> counter(v);
+  SizeCounter<std::vector<int>> counter1(&v);
+  SizeCounter<std::vector<int>> counter2;
+  counter2.observe(&v);
 
-  size_t observation = counter; // implicit conversion
-  BOOST_CHECK_EQUAL(observation, 0);
+  size_t observation1 = counter1; // implicit conversion
+  size_t observation2 = counter2;
+  BOOST_CHECK_EQUAL(observation1, 0);
+  BOOST_CHECK_EQUAL(observation2, 0);
 
   v.resize(249);
-  BOOST_CHECK_EQUAL(counter, 249);
+  BOOST_CHECK_EQUAL(counter1, 249);
+  BOOST_CHECK_EQUAL(counter2, 249);
 
   v.resize(98);
-  BOOST_CHECK_EQUAL(counter, 98);
+  BOOST_CHECK_EQUAL(counter1, 98);
+  BOOST_CHECK_EQUAL(counter2, 98);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestCounter