table: make FIB and StrategyChoice iterators default-constructible

They were previously not default-constructible when compiled with gcc 4.8.4.

refs #3882

Change-Id: I2431c869fb61b7adbe83d5551705981bf8618280
diff --git a/.waf-tools/type_traits.py b/.waf-tools/type_traits.py
index 07eb129..fc1ffbf 100644
--- a/.waf-tools/type_traits.py
+++ b/.waf-tools/type_traits.py
@@ -6,23 +6,12 @@
 
 from waflib import Configure
 
-IS_DEFAULT_CONSTRUCTIBLE_CHECK = '''
-#include <type_traits>
-static_assert(std::is_default_constructible<int>::value, "");
-'''
-
 IS_MOVE_CONSTRUCTIBLE_CHECK = '''
 #include <type_traits>
 static_assert(std::is_move_constructible<int>::value, "");
 '''
 
 def configure(conf):
-    if conf.check_cxx(msg='Checking for std::is_default_constructible',
-                      fragment=IS_DEFAULT_CONSTRUCTIBLE_CHECK,
-                      features='cxx', mandatory=False):
-        conf.define('HAVE_IS_DEFAULT_CONSTRUCTIBLE', 1)
-        conf.env['HAVE_IS_DEFAULT_CONSTRUCTIBLE'] = True
-
     if conf.check_cxx(msg='Checking for std::is_move_constructible',
                       fragment=IS_MOVE_CONSTRUCTIBLE_CHECK,
                       features='cxx', mandatory=False):
diff --git a/core/asserts.hpp b/core/asserts.hpp
new file mode 100644
index 0000000..cef39b4
--- /dev/null
+++ b/core/asserts.hpp
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016,  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,
+ *                           The University of Memphis.
+ *
+ * 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 NFD_CORE_ASSERTS_HPP
+#define NFD_CORE_ASSERTS_HPP
+
+#include "common.hpp"
+#include <boost/concept/assert.hpp>
+#include <boost/concept_check.hpp>
+#include <type_traits>
+
+namespace nfd {
+namespace detail {
+
+// As of Boost 1.54.0, the internal implementation of BOOST_CONCEPT_ASSERT does not allow
+// multiple assertions on the same line, so we have to combine multiple concepts together.
+
+template<typename T>
+class StlForwardIteratorConcept : public boost::ForwardIterator<T>
+                                , public boost::DefaultConstructible<T>
+{
+};
+
+} // namespace detail
+} // namespace nfd
+
+/** \brief assert T is default constructible
+ *  \sa http://en.cppreference.com/w/cpp/concept/DefaultConstructible
+ */
+#define NFD_ASSERT_DEFAULT_CONSTRUCTIBLE(T) \
+  static_assert(std::is_default_constructible<T>::value, \
+                #T " must be default-constructible"); \
+  BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<T>))
+
+/** \brief assert T is a forward iterator
+ *  \sa http://en.cppreference.com/w/cpp/concept/ForwardIterator
+ *  \note A forward iterator should be default constructible, but boost::ForwardIterator follows
+ *        SGI standard which doesn't require DefaultConstructible, so a separate check is needed.
+ */
+#define NFD_ASSERT_FORWARD_ITERATOR(T) \
+  BOOST_CONCEPT_ASSERT((::nfd::detail::StlForwardIteratorConcept<T>)); \
+  static_assert(std::is_default_constructible<T>::value, \
+                #T " must be default-constructible")
+
+#endif // NFD_CORE_ASSERTS_HPP
diff --git a/daemon/fw/face-table.cpp b/daemon/fw/face-table.cpp
index ed082bf..aaee894 100644
--- a/daemon/fw/face-table.cpp
+++ b/daemon/fw/face-table.cpp
@@ -25,12 +25,15 @@
 
 #include "face-table.hpp"
 #include "forwarder.hpp"
+#include "core/asserts.hpp"
 #include "core/global-io.hpp"
 #include "core/logger.hpp"
 #include "face/channel.hpp"
 
 namespace nfd {
 
+NFD_ASSERT_FORWARD_ITERATOR(FaceTable::const_iterator);
+
 NFD_LOG_INIT("FaceTable");
 
 FaceTable::FaceTable()
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index dd72214..89c54e9 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -24,25 +24,17 @@
  */
 
 #include "cs.hpp"
-#include "core/logger.hpp"
 #include "core/algorithm.hpp"
+#include "core/asserts.hpp"
+#include "core/logger.hpp"
 #include <ndn-cxx/lp/tags.hpp>
 
-NFD_LOG_INIT("ContentStore");
-
 namespace nfd {
 namespace cs {
 
-// http://en.cppreference.com/w/cpp/concept/ForwardIterator
-BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Cs::const_iterator>));
-// boost::ForwardIterator follows SGI standard http://www.sgi.com/tech/stl/ForwardIterator.html,
-// which doesn't require DefaultConstructible
-#ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
-static_assert(std::is_default_constructible<Cs::const_iterator>::value,
-              "Cs::const_iterator must be default-constructible");
-#else
-BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Cs::const_iterator>));
-#endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE
+NFD_ASSERT_FORWARD_ITERATOR(Cs::const_iterator);
+
+NFD_LOG_INIT("ContentStore");
 
 unique_ptr<Policy>
 makeDefaultPolicy()
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index 8ba6ffe..c34fd12 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -26,26 +26,14 @@
 #include "fib.hpp"
 #include "pit-entry.hpp"
 #include "measurements-entry.hpp"
-
-#include <boost/concept/assert.hpp>
-#include <boost/concept_check.hpp>
-#include <type_traits>
+#include "core/asserts.hpp"
 
 namespace nfd {
 namespace fib {
 
-const unique_ptr<Entry> Fib::s_emptyEntry = make_unique<Entry>(Name());
+NFD_ASSERT_FORWARD_ITERATOR(Fib::const_iterator);
 
-// http://en.cppreference.com/w/cpp/concept/ForwardIterator
-BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Fib::const_iterator>));
-// boost::ForwardIterator follows SGI standard http://www.sgi.com/tech/stl/ForwardIterator.html,
-// which doesn't require DefaultConstructible
-#ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
-static_assert(std::is_default_constructible<Fib::const_iterator>::value,
-              "Fib::const_iterator must be default-constructible");
-#else
-BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Fib::const_iterator>));
-#endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE
+const unique_ptr<Entry> Fib::s_emptyEntry = make_unique<Entry>(Name());
 
 static inline bool
 nteHasFibEntry(const name_tree::Entry& nte)
diff --git a/daemon/table/name-tree-entry.hpp b/daemon/table/name-tree-entry.hpp
index ab385da..2fa0806 100644
--- a/daemon/table/name-tree-entry.hpp
+++ b/daemon/table/name-tree-entry.hpp
@@ -189,8 +189,11 @@
    */
   using Getter = ENTRY* (Entry::*)() const;
 
+  /** \note The default argument is needed to ensure FIB and StrategyChoice iterators
+   *        are default-constructible.
+   */
   explicit
-  GetTableEntry(Getter getter)
+  GetTableEntry(Getter getter = nullptr)
     : m_getter(getter)
   {
   }
diff --git a/daemon/table/name-tree-iterator.cpp b/daemon/table/name-tree-iterator.cpp
index d7c7362..32f282d 100644
--- a/daemon/table/name-tree-iterator.cpp
+++ b/daemon/table/name-tree-iterator.cpp
@@ -25,20 +25,14 @@
 
 #include "name-tree-iterator.hpp"
 #include "name-tree.hpp"
+#include "core/asserts.hpp"
 #include "core/logger.hpp"
-
-#include <boost/concept/assert.hpp>
-#include <boost/concept_check.hpp>
 #include <boost/range/concepts.hpp>
-#include <type_traits>
 
 namespace nfd {
 namespace name_tree {
 
-BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Iterator>));
-static_assert(std::is_default_constructible<Iterator>::value,
-              "Iterator must be default-constructible");
-
+NFD_ASSERT_FORWARD_ITERATOR(Iterator);
 BOOST_CONCEPT_ASSERT((boost::ForwardRangeConcept<Range>));
 
 NFD_LOG_INIT("NameTreeIterator");
diff --git a/daemon/table/pit-iterator.cpp b/daemon/table/pit-iterator.cpp
index b3b9afa..973342e 100644
--- a/daemon/table/pit-iterator.cpp
+++ b/daemon/table/pit-iterator.cpp
@@ -24,17 +24,12 @@
  */
 
 #include "pit-iterator.hpp"
-
-#include <boost/concept/assert.hpp>
-#include <boost/concept_check.hpp>
-#include <type_traits>
+#include "core/asserts.hpp"
 
 namespace nfd {
 namespace pit {
 
-BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Iterator>));
-static_assert(std::is_default_constructible<Iterator>::value,
-              "Iterator must be default-constructible");
+NFD_ASSERT_FORWARD_ITERATOR(Iterator);
 
 Iterator::Iterator(const NameTree::const_iterator& ntIt, size_t iPitEntry)
   : m_ntIt(ntIt)
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index d801870..06acaae 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -26,6 +26,7 @@
 #include "strategy-choice.hpp"
 #include "measurements-entry.hpp"
 #include "pit-entry.hpp"
+#include "core/asserts.hpp"
 #include "core/logger.hpp"
 #include "fw/strategy.hpp"
 
@@ -34,6 +35,8 @@
 
 using fw::Strategy;
 
+NFD_ASSERT_FORWARD_ITERATOR(StrategyChoice::const_iterator);
+
 NFD_LOG_INIT("StrategyChoice");
 
 static inline bool
diff --git a/tests/daemon/table/strategy-choice.t.cpp b/tests/daemon/table/strategy-choice.t.cpp
index fae7b49..ebcd9db 100644
--- a/tests/daemon/table/strategy-choice.t.cpp
+++ b/tests/daemon/table/strategy-choice.t.cpp
@@ -204,10 +204,6 @@
   BOOST_CHECK_EQUAL(nameTree.size(), nNameTreeEntriesBefore);
 }
 
-//XXX BOOST_CONCEPT_ASSERT((ForwardIterator<std::vector<int>::iterator>))
-//    is also failing. There might be a problem with ForwardIterator concept checking.
-//BOOST_CONCEPT_ASSERT((ForwardIterator<StrategyChoice::const_iterator>));
-
 BOOST_AUTO_TEST_CASE(Enumerate)
 {
   sc.insert("/",      strategyNameP);