Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorYuri Gorshenin <y@maps.me>2016-05-26 17:38:33 +0300
committerYuri Gorshenin <y@maps.me>2016-05-26 17:38:33 +0300
commit60e74b995a0d8bd6a00c08c8d5483ea090c2d20e (patch)
treea604541873fff5a0b73f920bb09cf77792a6ff47 /base
parent6f84875fb9912ef2d199418605362c1e427db578 (diff)
[base] Implemented EqualsBy.
Diffstat (limited to 'base')
-rw-r--r--base/base_tests/stl_helpers_test.cpp57
-rw-r--r--base/stl_helpers.hpp76
2 files changed, 97 insertions, 36 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