table: make NameTree enumeration usable with range-based for

NameTree::fullEnumerate and NameTree::partialEnumerate are changed
to return a type usable with range-based for.

NameTree enumeration test cases are also simplified.

refs #2155

Change-Id: I315d9502d2194670aa7054ab956ededefb0c7ca0
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index a3b836e..99a1bf9 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -143,23 +143,33 @@
 void
 Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
 {
-  for (NameTree::const_iterator it = m_nameTree.fullEnumerate(
-       &predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end();) {
-    shared_ptr<fib::Entry> entry = it->getFibEntry();
+  shared_ptr<fib::Entry> toErase;
 
-    ++it; // advance the iterator before `erase` invalidates it
+  auto&& enumerable = m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry);
+  for (const name_tree::Entry& nte : enumerable) {
+    if (toErase != nullptr) {
+      this->erase(*toErase);
+      toErase.reset();
+    }
 
+    shared_ptr<fib::Entry> entry = nte.getFibEntry();
     entry->removeNextHop(face);
     if (!entry->hasNextHops()) {
-      this->erase(*entry);
+      toErase = entry;
+      // entry needs to be erased, but we must wait until next iteration
+      // to erase it because otherwise it would invalidate the iterator
     }
   }
+
+  if (toErase != nullptr) {
+    this->erase(*toErase);
+  }
 }
 
 Fib::const_iterator
 Fib::begin() const
 {
-  return const_iterator(m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry));
+  return const_iterator(m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry).begin());
 }
 
 } // namespace nfd