diff --git a/base/base_tests/stl_helpers_test.cpp b/base/base_tests/stl_helpers_test.cpp index aac0393117..ac60b8c064 100644 --- a/base/base_tests/stl_helpers_test.cpp +++ b/base/base_tests/stl_helpers_test.cpp @@ -83,26 +83,35 @@ UNIT_TEST(SortUnique) TEST_EQUAL(v, expected, ()); } -UNIT_TEST(SortUniquePred) +UNIT_TEST(SortUniqueCompPredTest1) { - struct Foo - { - int i, j; - }; + using TValue = int; + using TPair = pair; + vector v = + {{1, 22}, {2, 33}, {1, 23}, {4, 54}, {3, 34}, {5, 23}, {2, 23}, {7, 32}, {1, 12}}; - vector v = {{1, 22}, {2, 33}, {1, 23}, {4, 54}, {3, 34}, {5, 23}, {2, 23}, {7, 32}, {1, 12}}; - my::SortUnique([](Foo const & f1, Foo const & f2) - { - return f1.i < f2.i; - }, - v); + my::SortUnique(v, my::CompareBy(&TPair::first), + [](TPair const & p1, TPair const & p2) { return p1.first == p2.first; }); - TEST_EQUAL(v.size(), 6, ()); - TEST_EQUAL(v[0].i, 1, ()); - TEST_EQUAL(v[1].i, 2, ()); - TEST_EQUAL(v[2].i, 3, ()); - TEST_EQUAL(v[3].i, 4, ()); - TEST_EQUAL(v[4].i, 5, ()); - TEST_EQUAL(v[5].i, 7, ()); + vector const expected = {1, 2, 3, 4, 5, 7}; + TEST_EQUAL(v.size(), expected.size(), ()); + for (int i = 0; i < v.size(); ++i) + TEST_EQUAL(v[i].first, expected[i], (i)); +} + +UNIT_TEST(SortUniqueCompPredTest2) +{ + using TValue = double; + using TPair = pair; + vector v = + {{0.5, 11}, {1000.99, 234}, {0.5, 23}, {1234.56789, 54}, {1000.99, 34}}; + + my::SortUnique(v, my::CompareBy(&TPair::first), + [](TPair const & p1, TPair const & p2) { return p1.first == p2.first; }); + + vector const expected = {0.5, 1000.99, 1234.56789}; + TEST_EQUAL(v.size(), expected.size(), ()); + for (int i = 0; i < v.size(); ++i) + TEST_EQUAL(v[i].first, expected[i], (i)); } } // namespace diff --git a/base/stl_helpers.hpp b/base/stl_helpers.hpp index 035b77e161..b11f95eec7 100644 --- a/base/stl_helpers.hpp +++ b/base/stl_helpers.hpp @@ -86,20 +86,13 @@ void SortUnique(vector & v) v.erase(unique(v.begin(), v.end()), v.end()); } -// Sorts and removes duplicate entries from |v| according to |comp|. -// Note. If several entries are equivalent according to |comp| an arbitrary entry of them -// is left in |v| after a call of this method. -// Note. |comp| should implement operator<. It means the expression -// !comp(t1, t2) && !comp(t2, t1) should return true iff t1 is equivalent to t2. -// It's necessary for std::unique. -template -void SortUnique(function const & comp, vector & v) +// Sorts according to |comp| and removes duplicate entries according to |pred| from |v|. +// Note. If several entries are equal according to |pred| an arbitrary entry of them +// is left in |v| after a call of this function. +template +void SortUnique(vector & v, TComp && comp, TPred && pred) { sort(v.begin(), v.end(), comp); - function const pred = [&comp](T const & t1, T const & t2) - { - return !comp(t1, t2) && !comp(t2, t1); - }; v.erase(unique(v.begin(), v.end(), pred), v.end()); }