<div dir="ltr">Should this just be implemented for ranges rather than iterator parameters?<br><br><div class="gmail_quote"><div dir="ltr">On Wed, Jan 17, 2018 at 12:34 AM Michael Spencer via Phabricator via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Bigcheese created this revision.<br>
<br>
This is for <a href="https://reviews.llvm.org/D36351" rel="noreferrer" target="_blank">https://reviews.llvm.org/D36351</a><br>
<br>
This adds the merge_unique algorithm. It's like std::unique except it allows modifying the uniqued values.<br>
<br>
<br>
Repository:<br>
  rL LLVM<br>
<br>
<a href="https://reviews.llvm.org/D42163" rel="noreferrer" target="_blank">https://reviews.llvm.org/D42163</a><br>
<br>
Files:<br>
  include/llvm/ADT/STLExtras.h<br>
  unittests/ADT/STLExtrasTest.cpp<br>
<br>
<br>
Index: unittests/ADT/STLExtrasTest.cpp<br>
===================================================================<br>
--- unittests/ADT/STLExtrasTest.cpp<br>
+++ unittests/ADT/STLExtrasTest.cpp<br>
@@ -364,4 +364,17 @@<br>
   EXPECT_EQ(5, count);<br>
 }<br>
<br>
+TEST(STLExtrasTest, merge_unique) {<br>
+  int a[] = {1, 2, 2, 2, 2, 3, 4, 5, 5};<br>
+  auto end = merge_unique(std::begin(a), std::end(a),<br>
+                          [](int a, int b) { return a == b; },<br>
+                          [](int &a, int b) { a += b; });<br>
+  EXPECT_EQ(a + 6, end);<br>
+  EXPECT_EQ(1, a[0]);<br>
+  EXPECT_EQ(4, a[1]);<br>
+  EXPECT_EQ(4, a[2]);<br>
+  EXPECT_EQ(3, a[3]);<br>
+  EXPECT_EQ(4, a[4]);<br>
+  EXPECT_EQ(10, a[5]);<br>
+}<br>
 } // namespace<br>
Index: include/llvm/ADT/STLExtras.h<br>
===================================================================<br>
--- include/llvm/ADT/STLExtras.h<br>
+++ include/llvm/ADT/STLExtras.h<br>
@@ -932,6 +932,38 @@<br>
   C.erase(remove_if(C, P), C.end());<br>
 }<br>
<br>
+/// Like `std::unique`, but calls \p Merge on equal values. \p Merge is allowed<br>
+/// to modifiy its first argument.<br>
+///<br>
+/// \param Merge a binary callable with a signature callable as<br>
+///   `Merge(*declval<ForwardIt>(), *declval<ForwardIt>())`<br>
+///<br>
+/// Example:<br>
+///<br>
+///   int a[] = {1, 2, 2, 3, 4, 5, 5};<br>
+///   auto end = merge_unique(std::begin(a), std::end(a),<br>
+///     [](int a, int b) { return a == b; },<br>
+///     [](int &a, int b) { a += b; });<br>
+///<br>
+///   for (auto i = a; i != end; ++i)<br>
+///     std::cout << *i << " ";<br>
+///<br>
+///   -- 1 4 3 4 10<br>
+template <class ForwardIt, class PredTy, class MergeTy><br>
+ForwardIt merge_unique(ForwardIt First, ForwardIt Last, PredTy Pred, MergeTy Merge) {<br>
+  if (First == Last)<br>
+    return Last;<br>
+<br>
+  ForwardIt I = First;<br>
+  while (++I != Last) {<br>
+    if (Pred(*First, *I))<br>
+      Merge(*First, *I);<br>
+    else if (++First != I)<br>
+      *First = std::move(*I);<br>
+  }<br>
+  return ++First;<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //     Extra additions to <memory><br>
 //===----------------------------------------------------------------------===//<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>