Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -932,6 +932,38 @@ C.erase(remove_if(C, P), C.end()); } +/// Like `std::unique`, but calls \p Merge on equal values. \p Merge is allowed +/// to modifiy its first argument. +/// +/// \param Merge a binary callable with a signature callable as +/// `Merge(*declval(), *declval())` +/// +/// Example: +/// +/// int a[] = {1, 2, 2, 3, 4, 5, 5}; +/// auto end = merge_unique(std::begin(a), std::end(a), +/// [](int a, int b) { return a == b; }, +/// [](int &a, int b) { a += b; }); +/// +/// for (auto i = a; i != end; ++i) +/// std::cout << *i << " "; +/// +/// -- 1 4 3 4 10 +template +ForwardIt merge_unique(ForwardIt First, ForwardIt Last, PredTy Pred, MergeTy Merge) { + if (First == Last) + return Last; + + ForwardIt I = First; + while (++I != Last) { + if (Pred(*First, *I)) + Merge(*First, *I); + else if (++First != I) + *First = std::move(*I); + } + return ++First; +} + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// Index: unittests/ADT/STLExtrasTest.cpp =================================================================== --- unittests/ADT/STLExtrasTest.cpp +++ unittests/ADT/STLExtrasTest.cpp @@ -364,4 +364,17 @@ EXPECT_EQ(5, count); } +TEST(STLExtrasTest, merge_unique) { + int a[] = {1, 2, 2, 2, 2, 3, 4, 5, 5}; + auto end = merge_unique(std::begin(a), std::end(a), + [](int a, int b) { return a == b; }, + [](int &a, int b) { a += b; }); + EXPECT_EQ(a + 6, end); + EXPECT_EQ(1, a[0]); + EXPECT_EQ(4, a[1]); + EXPECT_EQ(4, a[2]); + EXPECT_EQ(3, a[3]); + EXPECT_EQ(4, a[4]); + EXPECT_EQ(10, a[5]); +} } // namespace