[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