table: Ensure Fib::const_iterator is default and copy constructible
This functionality is necessary for ndnSIM python bindings and is
technically required by ForwardIterator C++ concept
(http://en.cppreference.com/w/cpp/concept/ForwardIterator)
Change-Id: Ibe0812c3a2cf05840cd3e83b941cc52affe2ac65
Refs: #2338
diff --git a/daemon/table/name-tree.cpp b/daemon/table/name-tree.cpp
index d7cb544..3ac469d 100644
--- a/daemon/table/name-tree.cpp
+++ b/daemon/table/name-tree.cpp
@@ -27,10 +27,25 @@
#include "core/logger.hpp"
#include "core/city-hash.hpp"
+#include <boost/concept/assert.hpp>
+#include <boost/concept_check.hpp>
+#include <type_traits>
+
namespace nfd {
NFD_LOG_INIT("NameTree");
+// http://en.cppreference.com/w/cpp/concept/ForwardIterator
+BOOST_CONCEPT_ASSERT((boost::ForwardIterator<NameTree::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<NameTree::const_iterator>::value,
+ "NameTree::const_iterator must be default-constructible");
+#else
+BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<NameTree::const_iterator>));
+#endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE
+
namespace name_tree {
class Hash32
@@ -569,12 +584,17 @@
output << "--------------------------\n";
}
+NameTree::const_iterator::const_iterator()
+ : m_nameTree(nullptr)
+{
+}
+
NameTree::const_iterator::const_iterator(NameTree::IteratorType type,
const NameTree& nameTree,
shared_ptr<name_tree::Entry> entry,
const name_tree::EntrySelector& entrySelector,
const name_tree::EntrySubTreeSelector& entrySubTreeSelector)
- : m_nameTree(nameTree)
+ : m_nameTree(&nameTree)
, m_entry(entry)
, m_subTreeRoot(entry)
, m_entrySelector(make_shared<name_tree::EntrySelector>(entrySelector))
@@ -590,7 +610,7 @@
{
NFD_LOG_TRACE("const_iterator::operator++()");
- BOOST_ASSERT(m_entry != m_nameTree.m_end);
+ BOOST_ASSERT(m_entry != m_nameTree->m_end);
if (m_type == FULL_ENUMERATE_TYPE) // fullEnumerate
{
@@ -608,12 +628,12 @@
// process other buckets
- for (int newLocation = m_entry->m_hash % m_nameTree.m_nBuckets + 1;
- newLocation < static_cast<int>(m_nameTree.m_nBuckets);
+ for (int newLocation = m_entry->m_hash % m_nameTree->m_nBuckets + 1;
+ newLocation < static_cast<int>(m_nameTree->m_nBuckets);
++newLocation)
{
// process each bucket
- name_tree::Node* node = m_nameTree.m_buckets[newLocation];
+ name_tree::Node* node = m_nameTree->m_buckets[newLocation];
while (node != 0)
{
m_entry = node->m_entry;
@@ -627,7 +647,7 @@
}
BOOST_VERIFY(isFound == false);
// Reach to the end()
- m_entry = m_nameTree.m_end;
+ m_entry = m_nameTree->m_end;
return *this;
}
@@ -727,7 +747,7 @@
}
}
- m_entry = m_nameTree.m_end;
+ m_entry = m_nameTree->m_end;
return *this;
}
@@ -745,7 +765,7 @@
}
// Reach to the end (Root)
- m_entry = m_nameTree.m_end;
+ m_entry = m_nameTree->m_end;
return *this;
}