<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>