<div dir="ltr"><div>Here's the latest iteration.  Added doxygen comments and removed postfix ++ operator and operator==.  Also removed the overload of llvm::enumerate() and used a single function that takes an rvalue reference instead of overloading on const Range& and Range&</div><div><br></div><div>From ae8f3cb0a9d1958b4c2dd3fcff84e22cd9bb4ba9 Mon Sep 17 00:00:00 2001</div><div>From: Zachary Turner <<a href="mailto:zturner@google.com">zturner@google.com</a>></div><div>Date: Thu, 29 Sep 2016 11:13:38 -0700</div><div>Subject: [PATCH] Add llvm::enumerate to STLExtras.</div><div><br></div><div>---</div><div> include/llvm/ADT/STLExtras.h    | 54 +++++++++++++++++++++++++++++++++++++++++</div><div> unittests/ADT/STLExtrasTest.cpp | 42 ++++++++++++++++++++++++++++++++</div><div> 2 files changed, 96 insertions(+)</div><div><br></div><div>diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h</div><div>index e6215e4..63f919d 100644</div><div>--- a/include/llvm/ADT/STLExtras.h</div><div>+++ b/include/llvm/ADT/STLExtras.h</div><div>@@ -626,6 +626,60 @@ template <typename T> struct deref {</div><div>   }</div><div> };</div><div><br></div><div>+namespace detail {</div><div>+template <typename I, typename V> class enumerator_impl {</div><div>+public:</div><div>+  template <typename V> struct result_pair {</div><div>+    result_pair(std::size_t Index, V Value) : Index(Index), Value(Value) {}</div><div>+</div><div>+    const std::size_t Index;</div><div>+    V Value;</div><div>+  };</div><div>+</div><div>+  template <typename I, typename V> struct iterator {</div><div>+    iterator(I Iter, std::size_t Index) : Iter(Iter), Index(Index) {}</div><div>+</div><div>+    result_pair<const V> operator*() const {</div><div>+      return result_pair<const V>(Index, *Iter);</div><div>+    }</div><div>+    result_pair<V> operator*() { return result_pair<V>(Index, *Iter); }</div><div>+</div><div>+    iterator &operator++() {</div><div>+      ++Iter;</div><div>+      ++Index;</div><div>+      return *this;</div><div>+    }</div><div>+</div><div>+    bool operator!=(const iterator &RHS) const { return Iter != RHS.Iter; }</div><div>+</div><div>+  private:</div><div>+    I Iter;</div><div>+    std::size_t Index;</div><div>+  };</div><div>+</div><div>+  explicit enumerator_impl(I Begin, I End) : Begin(Begin), End(End) {}</div><div>+</div><div>+  iterator<I, V> begin() { return iterator<I, V>(Begin, 0); }</div><div>+  iterator<I, V> end() { return iterator<I, V>(End, std::size_t(-1)); }</div><div>+</div><div>+  iterator<I, V> begin() const { return iterator<I, V>(Begin, 0); }</div><div>+  iterator<I, V> end() const { return iterator<I, V>(End, std::size_t(-1)); }</div><div>+</div><div>+private:</div><div>+  I Begin;</div><div>+  I End;</div><div>+};</div><div>+}</div><div>+</div><div>+/// Given an input range, returns a new range whose values are are pair (A,B)</div><div>+/// such that A is the 0-based index of the item in the sequence, and B is</div><div>+/// the value from the original sequence.</div><div>+template <typename R> auto enumerate(R &&Range) {</div><div>+  typedef decltype(std::begin(Range)) I;</div><div>+  typedef decltype(*std::begin(Range)) V;</div><div>+  return detail::enumerator_impl<I, V>(std::begin(Range), std::end(Range));</div><div>+}</div><div>+</div><div> } // End llvm namespace</div><div><br></div><div> #endif</div><div>diff --git a/unittests/ADT/STLExtrasTest.cpp b/unittests/ADT/STLExtrasTest.cpp</div><div>index dc62b03..d7457f5 100644</div><div>--- a/unittests/ADT/STLExtrasTest.cpp</div><div>+++ b/unittests/ADT/STLExtrasTest.cpp</div><div>@@ -10,6 +10,8 @@</div><div> #include "llvm/ADT/STLExtras.h"</div><div> #include "gtest/gtest.h"</div><div><br></div><div>+#include <vector></div><div>+</div><div> using namespace llvm;</div><div><br></div><div> namespace {</div><div>@@ -37,4 +39,44 @@ TEST(STLExtrasTest, Rank) {</div><div>   EXPECT_EQ(4, f(rank<6>()));</div><div> }</div><div><br></div><div>+TEST(STLExtrasTest, Enumerate) {</div><div>+  std::vector<char> foo = {'a', 'b', 'c'};</div><div>+</div><div>+  std::vector<std::pair<std::size_t, char>> results;</div><div>+</div><div>+  for (auto X : llvm::enumerate(foo)) {</div><div>+    results.push_back(std::make_pair(X.Index, X.Value));</div><div>+  }</div><div>+  ASSERT_EQ(3, results.size());</div><div>+  EXPECT_EQ(0, results[0].first);</div><div>+  EXPECT_EQ('a', results[0].second);</div><div>+  EXPECT_EQ(1, results[1].first);</div><div>+  EXPECT_EQ('b', results[1].second);</div><div>+  EXPECT_EQ(2, results[2].first);</div><div>+  EXPECT_EQ('c', results[2].second);</div><div>+</div><div>+  results.clear();</div><div>+  const std::vector<int> bar = {'1', '2', '3'};</div><div>+  for (auto X : llvm::enumerate(bar)) {</div><div>+    results.push_back(std::make_pair(X.Index, X.Value));</div><div>+  }</div><div>+  EXPECT_EQ(0, results[0].first);</div><div>+  EXPECT_EQ('1', results[0].second);</div><div>+  EXPECT_EQ(1, results[1].first);</div><div>+  EXPECT_EQ('2', results[1].second);</div><div>+  EXPECT_EQ(2, results[2].first);</div><div>+  EXPECT_EQ('3', results[2].second);</div><div>+}</div><div>+</div><div>+TEST(STLExtrasTest, EnumerateModify) {</div><div>+  std::vector<char> foo = {'a', 'b', 'c'};</div><div>+</div><div>+  for (auto X : llvm::enumerate(foo)) {</div><div>+    ++X.Value;</div><div>+  }</div><div>+</div><div>+  EXPECT_EQ('b', foo[0]);</div><div>+  EXPECT_EQ('c', foo[1]);</div><div>+  EXPECT_EQ('d', foo[2]);</div><div>+}</div><div> }</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Sep 29, 2016 at 1:33 PM Adrian McCarthy <<a href="mailto:amccarth@google.com">amccarth@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">I'm looking at <a href="http://en.cppreference.com/w/cpp/language/range-for" class="gmail_msg" target="_blank">http://en.cppreference.com/w/cpp/language/range-for</a>, which suggests that the range-based for is going to call begin and end on your range to get the iterators, and then use operator!= and operator++ (prefix) on the iterators.<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Since you're testing only with range-based for loops, perhaps the unnecessary bits should be cut (like operator== and operator++(int) (postfix)).  Either that or test those explicitly.</div></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Thu, Sep 29, 2016 at 1:11 PM, Zachary Turner <span dir="ltr" class="gmail_msg"><<a href="mailto:zturner@google.com" class="gmail_msg" target="_blank">zturner@google.com</a>></span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">I don't think so, but someone correct me if I'm wrong.  enumerator works with ranges, not iterators.  So by extension enumerate should also be considered to return a range, and not an iterator.  The baggage associated with ranges are much less than that associated with iterators.  As long as you have a begin and an end you're good to go.  <div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">But then again who knows, someone with more knowledge than me will have to chime in :)</div></div><div class="m_-8256014651112901752HOEnZb gmail_msg"><div class="m_-8256014651112901752h5 gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Thu, Sep 29, 2016 at 1:06 PM Adrian McCarthy <<a href="mailto:amccarth@google.com" class="gmail_msg" target="_blank">amccarth@google.com</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">Should `enumerator_impl::iterator` have the extra baggage for `std::iterator_traits`, like typedefs for `value_type`, `iterator_category`, and such?<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></div><div class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></div><div class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">On the other hand, if this is strictly for range-based for loops, then perhaps you don't even need the post-fix increment.</div><div class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></div></div><div class="gmail_extra m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div class="gmail_quote m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">On Thu, Sep 29, 2016 at 12:34 PM, Zachary Turner via llvm-commits <span dir="ltr" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><<a href="mailto:llvm-commits@lists.llvm.org" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><blockquote class="gmail_quote m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">Yes, you beat me to it.  I just used container in my example, but the implementation is supposed to work with any range</div><div class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814HOEnZb m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814h5 m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div class="gmail_quote m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div dir="ltr" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">On Thu, Sep 29, 2016 at 12:33 PM Krzysztof Parzyszek via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></div><blockquote class="gmail_quote m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 9/29/2016 2:27 PM, Krzysztof Parzyszek via llvm-commits wrote:<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
><br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
> How about enumerate(range) instead of container?<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
Nevermind.  It's the same thing.<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
--<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
hosted by The Linux Foundation<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
_______________________________________________<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
llvm-commits mailing list<br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<a href="mailto:llvm-commits@lists.llvm.org" class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a><br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
</blockquote></div>
</div></div><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">_______________________________________________<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
llvm-commits mailing list<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<a href="mailto:llvm-commits@lists.llvm.org" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg">
<br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></blockquote></div><br class="m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"></div>
</blockquote></div>
</div></div></blockquote></div><br class="gmail_msg"></div>
</blockquote></div>