<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 29, 2016, at 2:03 PM, Zachary Turner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">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 class=""><br class=""></div><div class="">From ae8f3cb0a9d1958b4c2dd3fcff84e22cd9bb4ba9 Mon Sep 17 00:00:00 2001</div><div class="">From: Zachary Turner <<a href="mailto:zturner@google.com" class="">zturner@google.com</a>></div><div class="">Date: Thu, 29 Sep 2016 11:13:38 -0700</div><div class="">Subject: [PATCH] Add llvm::enumerate to STLExtras.</div><div class=""><br class=""></div><div class="">---</div><div class=""> include/llvm/ADT/STLExtras.h    | 54 +++++++++++++++++++++++++++++++++++++++++</div><div class=""> unittests/ADT/STLExtrasTest.cpp | 42 ++++++++++++++++++++++++++++++++</div><div class=""> 2 files changed, 96 insertions(+)</div><div class=""><br class=""></div><div class="">diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h</div><div class="">index e6215e4..63f919d 100644</div><div class="">--- a/include/llvm/ADT/STLExtras.h</div><div class="">+++ b/include/llvm/ADT/STLExtras.h</div><div class="">@@ -626,6 +626,60 @@ template <typename T> struct deref {</div><div class="">   }</div><div class=""> };</div><div class=""><br class=""></div><div class="">+namespace detail {</div><div class="">+template <typename I, typename V> class enumerator_impl {</div><div class="">+public:</div><div class="">+  template <typename V> struct result_pair {</div><div class="">+    result_pair(std::size_t Index, V Value) : Index(Index), Value(Value) {}</div><div class="">+</div><div class="">+    const std::size_t Index;</div><div class="">+    V Value;</div><div class="">+  };</div><div class="">+</div><div class="">+  template <typename I, typename V> struct iterator {</div><div class="">+    iterator(I Iter, std::size_t Index) : Iter(Iter), Index(Index) {}</div><div class="">+</div><div class="">+    result_pair<const V> operator*() const {</div><div class="">+      return result_pair<const V>(Index, *Iter);</div><div class="">+    }</div><div class="">+    result_pair<V> operator*() { return result_pair<V>(Index, *Iter); }</div><div class="">+</div><div class="">+    iterator &operator++() {</div><div class="">+      ++Iter;</div><div class="">+      ++Index;</div><div class="">+      return *this;</div><div class="">+    }</div><div class="">+</div><div class="">+    bool operator!=(const iterator &RHS) const { return Iter != RHS.Iter; }</div><div class="">+</div><div class="">+  private:</div><div class="">+    I Iter;</div><div class="">+    std::size_t Index;</div><div class="">+  };</div><div class="">+</div><div class="">+  explicit enumerator_impl(I Begin, I End) : Begin(Begin), End(End) {}</div></div></div></blockquote><div><br class=""></div><div>I wonder if some iterators can be non-copyable? </div><div>Maybe move here?</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">+</div><div class="">+  iterator<I, V> begin() { return iterator<I, V>(Begin, 0); }</div><div class="">+  iterator<I, V> end() { return iterator<I, V>(End, std::size_t(-1)); }</div><div class="">+</div><div class="">+  iterator<I, V> begin() const { return iterator<I, V>(Begin, 0); }</div><div class="">+  iterator<I, V> end() const { return iterator<I, V>(End, std::size_t(-1)); }</div><div class="">+</div><div class="">+private:</div><div class="">+  I Begin;</div><div class="">+  I End;</div><div class="">+};</div><div class="">+}</div><div class="">+</div><div class="">+/// Given an input range, returns a new range whose values are are pair (A,B)</div><div class="">+/// such that A is the 0-based index of the item in the sequence, and B is</div><div class="">+/// the value from the original sequence.</div></div></div></blockquote><div><br class=""></div><div>I think it’d be great to have a snippet of pseudo-code included here.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">+template <typename R> auto enumerate(R &&Range) {</div><div class="">+  typedef decltype(std::begin(Range)) I;</div><div class="">+  typedef decltype(*std::begin(Range)) V;</div><div class="">+  return detail::enumerator_impl<I, V>(std::begin(Range), std::end(Range));</div><div class="">+}</div><div class="">+</div><div class=""> } // End llvm namespace</div><div class=""><br class=""></div><div class=""> #endif</div><div class="">diff --git a/unittests/ADT/STLExtrasTest.cpp b/unittests/ADT/STLExtrasTest.cpp</div><div class="">index dc62b03..d7457f5 100644</div><div class="">--- a/unittests/ADT/STLExtrasTest.cpp</div><div class="">+++ b/unittests/ADT/STLExtrasTest.cpp</div><div class="">@@ -10,6 +10,8 @@</div><div class=""> #include "llvm/ADT/STLExtras.h"</div><div class=""> #include "gtest/gtest.h"</div><div class=""><br class=""></div><div class="">+#include <vector></div><div class="">+</div><div class=""> using namespace llvm;</div><div class=""><br class=""></div><div class=""> namespace {</div><div class="">@@ -37,4 +39,44 @@ TEST(STLExtrasTest, Rank) {</div><div class="">   EXPECT_EQ(4, f(rank<6>()));</div><div class=""> }</div><div class=""><br class=""></div><div class="">+TEST(STLExtrasTest, Enumerate) {</div><div class="">+  std::vector<char> foo = {'a', 'b', 'c'};</div><div class="">+</div><div class="">+  std::vector<std::pair<std::size_t, char>> results;</div><div class="">+</div><div class="">+  for (auto X : llvm::enumerate(foo)) {</div><div class="">+    results.push_back(std::make_pair(X.Index, X.Value));</div><div class="">+  }</div><div class="">+  ASSERT_EQ(3, results.size());</div><div class="">+  EXPECT_EQ(0, results[0].first);</div><div class="">+  EXPECT_EQ('a', results[0].second);</div><div class="">+  EXPECT_EQ(1, results[1].first);</div><div class="">+  EXPECT_EQ('b', results[1].second);</div><div class="">+  EXPECT_EQ(2, results[2].first);</div><div class="">+  EXPECT_EQ('c', results[2].second);</div><div class="">+</div><div class="">+  results.clear();</div><div class="">+  const std::vector<int> bar = {'1', '2', '3'};</div><div class="">+  for (auto X : llvm::enumerate(bar)) {</div><div class="">+    results.push_back(std::make_pair(X.Index, X.Value));</div><div class="">+  }</div><div class="">+  EXPECT_EQ(0, results[0].first);</div><div class="">+  EXPECT_EQ('1', results[0].second);</div><div class="">+  EXPECT_EQ(1, results[1].first);</div><div class="">+  EXPECT_EQ('2', results[1].second);</div><div class="">+  EXPECT_EQ(2, results[2].first);</div><div class="">+  EXPECT_EQ('3', results[2].second);</div><div class="">+}</div><div class="">+</div><div class="">+TEST(STLExtrasTest, EnumerateModify) {</div><div class="">+  std::vector<char> foo = {'a', 'b', 'c'};</div><div class="">+</div><div class="">+  for (auto X : llvm::enumerate(foo)) {</div><div class="">+    ++X.Value;</div><div class="">+  }</div><div class="">+</div><div class="">+  EXPECT_EQ('b', foo[0]);</div><div class="">+  EXPECT_EQ('c', foo[1]);</div><div class="">+  EXPECT_EQ('d', foo[2]);</div><div class="">+}</div><div class=""> }</div></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>Can you add a test with an empty range?</div><div><br class=""></div><div>Otherwise, LGTM.</div><div><br class=""></div><div>Thanks,</div><div><br class=""></div><div>— </div><div>Mehdi</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Thu, Sep 29, 2016 at 1:33 PM Adrian McCarthy <<a href="mailto:amccarth@google.com" class="">amccarth@google.com</a>> wrote:<br class=""></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="gmail_msg m_-8256014651112901752HOEnZb"><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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"><div class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">Should `enumerator_impl::iterator` have the extra baggage for `std::iterator_traits`, like typedefs for `value_type`, `iterator_category`, and such?<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"></div><div class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"></div><div class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"></div></div><div class="gmail_extra m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"><<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814HOEnZb"><div class="m_-8256014651112901752m_4936607114054014688m_6561460641692223814h5 m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"><div class="gmail_quote m_-8256014651112901752m_4936607114054014688gmail_msg gmail_msg"><div dir="ltr" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">On Thu, Sep 29, 2016 at 12:33 PM Krzysztof Parzyszek via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_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="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
> How about enumerate(range) instead of container?<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
Nevermind.  It's the same thing.<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
--<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
hosted by The Linux Foundation<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
_______________________________________________<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
llvm-commits mailing list<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg m_-8256014651112901752m_4936607114054014688m_6561460641692223814m_6389614798378980395gmail_msg">
</blockquote></div>
</div></div><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">_______________________________________________<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">
llvm-commits mailing list<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">
<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg">
<br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"></blockquote></div><br class="gmail_msg m_-8256014651112901752m_4936607114054014688gmail_msg"></div>
</blockquote></div>
</div></div></blockquote></div><br class="gmail_msg"></div>
</blockquote></div>
_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits<br class=""></div></blockquote></div><br class=""></body></html>