diff options
-rw-r--r-- | base/base_tests/stl_helpers_test.cpp | 57 | ||||
-rw-r--r-- | base/stl_helpers.hpp | 76 | ||||
-rw-r--r-- | search/processor.cpp | 4 | ||||
-rw-r--r-- | search/reverse_geocoder.cpp | 4 | ||||
-rw-r--r-- | search/search_tests/locality_scorer_test.cpp | 2 | ||||
-rw-r--r-- | search/v2/geocoder.cpp | 2 |
6 files changed, 103 insertions, 42 deletions
diff --git a/base/base_tests/stl_helpers_test.cpp b/base/base_tests/stl_helpers_test.cpp index 7d23bdd3d2..f898d69e5b 100644 --- a/base/base_tests/stl_helpers_test.cpp +++ b/base/base_tests/stl_helpers_test.cpp @@ -19,30 +19,45 @@ private: int m_v; }; -UNIT_TEST(CompareBy_Field) +UNIT_TEST(LessBy) { - vector<pair<int, int>> v = {{2, 2}, {0, 4}, {3, 1}, {4, 0}, {1, 3}}; - sort(v.begin(), v.end(), my::CompareBy(&pair<int, int>::first)); - for (size_t i = 0; i < v.size(); ++i) - TEST_EQUAL(i, v[i].first, ()); - - vector<pair<int, int> const *> pv; - for (auto const & p : v) - pv.push_back(&p); - - sort(pv.begin(), pv.end(), my::CompareBy(&pair<int, int>::second)); - for (size_t i = 0; i < pv.size(); ++i) - TEST_EQUAL(i, pv[i]->second, ()); + using TValue = pair<int, int>; + + { + vector<TValue> v = {{2, 2}, {0, 4}, {3, 1}, {4, 0}, {1, 3}}; + sort(v.begin(), v.end(), my::LessBy(&TValue::first)); + for (size_t i = 0; i < v.size(); ++i) + TEST_EQUAL(i, v[i].first, ()); + + vector<TValue const *> pv; + for (auto const & p : v) + pv.push_back(&p); + + sort(pv.begin(), pv.end(), my::LessBy(&TValue::second)); + for (size_t i = 0; i < pv.size(); ++i) + TEST_EQUAL(i, pv[i]->second, ()); + } + + { + vector<Int> v; + for (int i = 9; i >= 0; --i) + v.emplace_back(i); + + sort(v.begin(), v.end(), my::LessBy(&Int::Get)); + for (size_t i = 0; i < v.size(); ++i) + TEST_EQUAL(v[i].Get(), static_cast<int>(i), ()); + } } -UNIT_TEST(CompareBy_Method) +UNIT_TEST(EqualsBy) { - vector<Int> v; - for (int i = 9; i >= 0; --i) - v.emplace_back(i); - - sort(v.begin(), v.end(), my::CompareBy(&Int::Get)); - for (size_t i = 0; i < v.size(); ++i) - TEST_EQUAL(v[i].Get(), static_cast<int>(i), ()); + using TValue = pair<int, int>; + vector<TValue> actual = {{1, 2}, {1, 3}, {2, 100}, {3, 7}, {3, 8}, {2, 500}}; + actual.erase(unique(actual.begin(), actual.end(), my::EqualsBy(&TValue::first)), actual.end()); + + vector<int> expected = {{1, 2, 3, 2}}; + TEST_EQUAL(expected.size(), actual.size(), ()); + for (size_t i = 0; i < actual.size(); ++i) + TEST_EQUAL(expected[i], actual[i].first, ()); } } // namespace diff --git a/base/stl_helpers.hpp b/base/stl_helpers.hpp index 3375867f75..c01fbc5b99 100644 --- a/base/stl_helpers.hpp +++ b/base/stl_helpers.hpp @@ -7,15 +7,16 @@ namespace my { namespace impl { -// When isField is true, Comparer operates on a pointers-to-field. -// Otherwise, Comparer operates on a pointers-to-const-method. +// When isField is true, following functors operate on a +// pointers-to-field. Otherwise, they operate on a +// pointers-to-const-method. template <bool isField, typename T, typename C> -struct Comparer; +struct Less; -template<typename T, typename C> -struct Comparer<true, T, C> +template <typename T, typename C> +struct Less<true, T, C> { - Comparer(T(C::*p)) : p_(p) {} + Less(T(C::*p)) : p_(p) {} inline bool operator()(C const & lhs, C const & rhs) const { return lhs.*p_ < rhs.*p_; } @@ -27,10 +28,10 @@ struct Comparer<true, T, C> T(C::*p_); }; -template<typename T, typename C> -struct Comparer<false, T, C> +template <typename T, typename C> +struct Less<false, T, C> { - Comparer(T (C::*p)() const) : p_(p) {} + Less(T (C::*p)() const) : p_(p) {} inline bool operator()(C const & lhs, C const & rhs) const { return (lhs.*p_)() < (rhs.*p_)(); } @@ -39,7 +40,40 @@ struct Comparer<false, T, C> return (lhs->*p_)() < (rhs->*p_)(); } - T(C::*p_)() const; + T (C::*p_)() const; +}; + +template <bool isField, typename T, typename C> +struct Equals; + +template <typename T, typename C> +struct Equals<true, T, C> +{ + Equals(T(C::*p)) : p_(p) {} + + inline bool operator()(C const & lhs, C const & rhs) const { return lhs.*p_ == rhs.*p_; } + + inline bool operator()(C const * const lhs, C const * const rhs) const + { + return lhs->*p_ == rhs->*p_; + } + + T(C::*p_); +}; + +template <typename T, typename C> +struct Equals<false, T, C> +{ + Equals(T (C::*p)() const) : p_(p) {} + + inline bool operator()(C const & lhs, C const & rhs) const { return (lhs.*p_)() == (rhs.*p_)(); } + + inline bool operator()(C const * const lhs, C const * const rhs) const + { + return (lhs->*p_)() == (rhs->*p_)(); + } + + T (C::*p_)() const; }; } // namespace impl @@ -60,17 +94,29 @@ void EraseIf(vector<T> & v, TFn && fn) // Creates a comparer being able to compare two instances of class C // (given by reference or pointer) by a field or const method of C. // For example, to create comparer that is able to compare pairs of -// ints by second component, it's enough to call CompareBy(&pair<int, +// ints by second component, it's enough to call LessBy(&pair<int, // int>::second). template <typename T, typename C> -impl::Comparer<true, T, C> CompareBy(T(C::*p)) +impl::Less<true, T, C> LessBy(T(C::*p)) +{ + return impl::Less<true, T, C>(p); +} + +template <typename T, typename C> +impl::Less<false, T, C> LessBy(T (C::*p)() const) +{ + return impl::Less<false, T, C>(p); +} + +template <typename T, typename C> +impl::Equals<true, T, C> EqualsBy(T(C::*p)) { - return impl::Comparer<true, T, C>(p); + return impl::Equals<true, T, C>(p); } template <typename T, typename C> -impl::Comparer<false, T, C> CompareBy(T (C::*p)() const) +impl::Equals<false, T, C> EqualsBy(T (C::*p)() const) { - return impl::Comparer<false, T, C>(p); + return impl::Equals<false, T, C>(p); } } // namespace my diff --git a/search/processor.cpp b/search/processor.cpp index 087f97af2e..aa8cada014 100644 --- a/search/processor.cpp +++ b/search/processor.cpp @@ -510,7 +510,7 @@ void Processor::FlushViewportResults(v2::Geocoder::Params const & params, Result if (indV.empty()) return; - sort(indV.begin(), indV.end(), my::CompareBy(&IndexedValue::GetDistanceToPivot)); + sort(indV.begin(), indV.end(), my::LessBy(&IndexedValue::GetDistanceToPivot)); for (size_t i = 0; i < indV.size(); ++i) { @@ -720,7 +720,7 @@ void Processor::FlushResults(v2::Geocoder::Params const & params, Results & res, if (indV.empty()) return; - sort(indV.rbegin(), indV.rend(), my::CompareBy(&IndexedValue::GetRank)); + sort(indV.rbegin(), indV.rend(), my::LessBy(&IndexedValue::GetRank)); // Do not process suggestions in additional search. if (!allMWMs || res.GetCount() == 0) diff --git a/search/reverse_geocoder.cpp b/search/reverse_geocoder.cpp index 4cccc1ed03..d91089c491 100644 --- a/search/reverse_geocoder.cpp +++ b/search/reverse_geocoder.cpp @@ -51,7 +51,7 @@ void ReverseGeocoder::GetNearbyStreets(MwmSet::MwmId const & id, m2::PointD cons if (mwmHandle.IsAlive()) { search::v2::MwmContext(move(mwmHandle)).ForEachFeature(rect, addStreet); - sort(streets.begin(), streets.end(), my::CompareBy(&Street::m_distanceMeters)); + sort(streets.begin(), streets.end(), my::LessBy(&Street::m_distanceMeters)); } } @@ -174,7 +174,7 @@ void ReverseGeocoder::GetNearbyBuildings(m2::PointD const & center, vector<Build }; m_index.ForEachInRect(addBuilding, rect, kQueryScale); - sort(buildings.begin(), buildings.end(), my::CompareBy(&Building::m_distanceMeters)); + sort(buildings.begin(), buildings.end(), my::LessBy(&Building::m_distanceMeters)); } // static diff --git a/search/search_tests/locality_scorer_test.cpp b/search/search_tests/locality_scorer_test.cpp index 020ee7c0b1..5021e24af7 100644 --- a/search/search_tests/locality_scorer_test.cpp +++ b/search/search_tests/locality_scorer_test.cpp @@ -98,7 +98,7 @@ public: void GetTopLocalities(size_t limit) { m_scorer.GetTopLocalities(limit, m_localities); - sort(m_localities.begin(), m_localities.end(), my::CompareBy(&Geocoder::Locality::m_featureId)); + sort(m_localities.begin(), m_localities.end(), my::LessBy(&Geocoder::Locality::m_featureId)); } // LocalityScorer::Delegate overrides: diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index f61dbf66da..568e33c9cb 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -1358,7 +1358,7 @@ void Geocoder::FindPaths() sortedLayers.reserve(m_layers.size()); for (auto & layer : m_layers) sortedLayers.push_back(&layer); - sort(sortedLayers.begin(), sortedLayers.end(), my::CompareBy(&FeaturesLayer::m_type)); + sort(sortedLayers.begin(), sortedLayers.end(), my::LessBy(&FeaturesLayer::m_type)); auto const & innermostLayer = *sortedLayers.front(); |