[PATCH] D38806: DepthFirstIterator.h: Use C++11 features to call a completed method onthe set type, instead of requiring that one exists.

Daniel Berlin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 11 09:42:23 PDT 2017


dberlin created this revision.
Herald added a subscriber: sanjoy.

This makes the required set type of df_iterator a normal set again.
Previously, you had to have a set type with the completed method,
which meant not being able to reuse exist set types.

I'm a bit unhappy about the overload hack required to do this, so
adding some reviewers to see if they know a better way.

(PostOrderIterator.h has a similar requirement that i'll fix as a
followup, but it requires more work).

Completion is also really a function that belongs as part of the
iterator, but it was non-trivial to simply make the iterator take it
as a function without a lot of other changes (due to the need for a
default argument, etc), due to the fun of trying to use lambdas as
template parameters.


https://reviews.llvm.org/D38806

Files:
  include/llvm/ADT/DepthFirstIterator.h


Index: include/llvm/ADT/DepthFirstIterator.h
===================================================================
--- include/llvm/ADT/DepthFirstIterator.h
+++ include/llvm/ADT/DepthFirstIterator.h
@@ -66,17 +66,29 @@
 // one more method, completed, which is invoked when all children of a
 // node have been processed. It is intended to distinguish of back and
 // cross edges in the spanning tree but is not used in the common case.
-template <typename NodeRef, unsigned SmallSize=8>
-struct df_iterator_default_set : public SmallPtrSet<NodeRef, SmallSize> {
-  using BaseSet = SmallPtrSet<NodeRef, SmallSize>;
-  using iterator = typename BaseSet::iterator;
-
-  std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); }
-  template <typename IterT>
-  void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); }
+// If completed exists in the set type, it is called.
+template <class NodeRef, unsigned SmallSize = 8>
+using df_iterator_default_set = SmallPtrSet<NodeRef, 8>;
+
+// This lets us detect if the set we've been handed has a completed method we
+// should be calling.  The int vs bool argument is to make it prefer one
+// overload over another in the case of ambiguity.  bool requires a conversion,
+// the int does not.
+template <typename T, typename NodeRef>
+auto call_completed_method_imp(T &t, NodeRef V, int)
+    -> decltype(t.completed(V), void()) {
+  return t.completed(V);
+}
+template <typename T, typename NodeRef>
+auto call_completed_method_imp(T &t, NodeRef V, bool) -> decltype(void()) {
+  return;
+}
 
-  void completed(NodeRef) {}
-};
+template <typename T, typename NodeRef>
+auto call_completed_method(T &t, NodeRef V)
+    -> decltype(call_completed_method_imp(t, V, 0), void()) {
+  call_completed_method_imp(t, V, 0);
+}
 
 // Generic Depth First Iterator
 template <class GraphT,
@@ -137,7 +149,7 @@
           return;
         }
       }
-      this->Visited.completed(Node);
+      call_completed_method(this->Visited, Node);
 
       // Oops, ran out of successors... go up a level on the stack.
       VisitStack.pop_back();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D38806.118632.patch
Type: text/x-patch
Size: 2095 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171011/70209151/attachment.bin>


More information about the llvm-commits mailing list