diff --git a/include/rusty_iterators/concepts.hpp b/include/rusty_iterators/concepts.hpp index 75a3ae4..2a58897 100644 --- a/include/rusty_iterators/concepts.hpp +++ b/include/rusty_iterators/concepts.hpp @@ -17,6 +17,12 @@ concept Comparable = requires(T first, T second) { { first > second } -> std::same_as; { first < second } -> std::same_as; }; + +template +concept EqFunctor = requires(Functor f, std::tuple t) { + { f(t) } -> std::same_as; +}; + template concept FilterFunctor = AllFunctor; @@ -37,10 +43,10 @@ concept Indexable = requires(T t) { }; template -concept PositionFunctor = AllFunctor; +concept InspectFunctor = ForEachFunctor; template -concept InspectFunctor = ForEachFunctor; +concept PositionFunctor = AllFunctor; template concept Summable = requires(T first, T second) { diff --git a/include/rusty_iterators/interface.hpp b/include/rusty_iterators/interface.hpp index 4944bf6..7254ee7 100644 --- a/include/rusty_iterators/interface.hpp +++ b/include/rusty_iterators/interface.hpp @@ -18,6 +18,7 @@ namespace rusty_iterators::interface using concepts::AllFunctor; using concepts::AnyFunctor; using concepts::Comparable; +using concepts::EqFunctor; using concepts::FilterFunctor; using concepts::FoldFunctor; using concepts::ForEachFunctor; @@ -76,6 +77,13 @@ class IterInterface template [[nodiscard]] auto chain(Second&& it) -> Chain; + template + [[nodiscard]] auto eq(Other&& it) -> bool; + + template + requires EqFunctor + [[nodiscard]] auto eqBy(Other&& it, Functor&& f) -> bool; + template requires FilterFunctor [[nodiscard]] auto filter(Functor&& f) -> Filter; @@ -244,6 +252,22 @@ auto rusty_iterators::interface::IterInterface::chain(Second&& it) return Chain{std::forward(self()), std::forward(it)}; } +template +template +auto rusty_iterators::interface::IterInterface::eq(Other&& it) -> bool +{ + return self().eqBy(std::forward(it), + [](auto x) { return std::get<0>(x) == std::get<1>(x); }); +} + +template +template + requires rusty_iterators::concepts::EqFunctor +auto rusty_iterators::interface::IterInterface::eqBy(Other&& it, Functor&& f) -> bool +{ + return self().zip(std::forward(it)).all(std::forward(f)); +} + template template requires rusty_iterators::iterator::FilterFunctor @@ -312,7 +336,7 @@ template requires rusty_iterators::concepts::Comparable auto rusty_iterators::interface::IterInterface::max() -> std::optional { - return reduce([](auto x, auto y) { return std::max(x, y); }); + return self().reduce([](auto x, auto y) { return std::max(x, y); }); } template @@ -320,7 +344,7 @@ template requires rusty_iterators::concepts::Comparable auto rusty_iterators::interface::IterInterface::min() -> std::optional { - return reduce([](auto x, auto y) { return std::min(x, y); }); + return self().reduce([](auto x, auto y) { return std::min(x, y); }); } template @@ -333,7 +357,7 @@ auto rusty_iterators::interface::IterInterface::movingWindow(size_t template auto rusty_iterators::interface::IterInterface::nth(size_t element) -> std::optional { - return advanceBy(element).next(); + return self().advanceBy(element).next(); } template @@ -379,7 +403,7 @@ template requires rusty_iterators::concepts::Summable auto rusty_iterators::interface::IterInterface::sum() -> R { - return fold(R{}, [](auto acc, auto x) { return acc + x; }); + return self().fold(R{}, [](auto acc, auto x) { return acc + x; }); } template diff --git a/tests/iterator.test.cpp b/tests/iterator.test.cpp index c568540..1062d8d 100644 --- a/tests/iterator.test.cpp +++ b/tests/iterator.test.cpp @@ -289,3 +289,32 @@ TEST(TestIterator, TestPositionNoValueMatched) ASSERT_EQ(result, std::nullopt); } + +TEST(TestIterator, TestEqWhenSame) +{ + auto v1 = std::vector{1, 2, 3}; + auto v2 = std::vector{1, 2, 3}; + + ASSERT_TRUE(LazyIterator{v1}.eq(LazyIterator{v2})); +} + +TEST(TestIterator, TestEqWhenDifferent) +{ + auto v1 = std::vector{1, 2, 3}; + auto v2 = std::vector{1, 2, 4}; + + ASSERT_FALSE(LazyIterator{v1}.eq(LazyIterator{v2})); +} + +TEST(TestIterator, TestEqBy) +{ + auto v1 = std::vector{"a", "bc", "dea"}; + auto v2 = std::vector{"j", "hg", "dfg"}; + + // Compare the vectors not by exact content, but by length of strings. + auto result = LazyIterator{v1}.eqBy(LazyIterator{v2}, [](auto x) { + return std::get<0>(x).get().size() == std::get<1>(x).get().size(); + }); + + ASSERT_TRUE(result); +}