Skip to content

Commit 6b20def

Browse files
feat: add eq and eqBy to iterator interface (#89)
1 parent 93ad4b7 commit 6b20def

3 files changed

Lines changed: 65 additions & 6 deletions

File tree

include/rusty_iterators/concepts.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ concept Comparable = requires(T first, T second) {
1717
{ first > second } -> std::same_as<bool>;
1818
{ first < second } -> std::same_as<bool>;
1919
};
20+
21+
template <class T, class Functor>
22+
concept EqFunctor = requires(Functor f, std::tuple<T, T> t) {
23+
{ f(t) } -> std::same_as<bool>;
24+
};
25+
2026
template <class T, class Functor>
2127
concept FilterFunctor = AllFunctor<T, Functor>;
2228

@@ -37,10 +43,10 @@ concept Indexable = requires(T t) {
3743
};
3844

3945
template <class T, class Functor>
40-
concept PositionFunctor = AllFunctor<T, Functor>;
46+
concept InspectFunctor = ForEachFunctor<T, Functor>;
4147

4248
template <class T, class Functor>
43-
concept InspectFunctor = ForEachFunctor<T, Functor>;
49+
concept PositionFunctor = AllFunctor<T, Functor>;
4450

4551
template <class T>
4652
concept Summable = requires(T first, T second) {

include/rusty_iterators/interface.hpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace rusty_iterators::interface
1818
using concepts::AllFunctor;
1919
using concepts::AnyFunctor;
2020
using concepts::Comparable;
21+
using concepts::EqFunctor;
2122
using concepts::FilterFunctor;
2223
using concepts::FoldFunctor;
2324
using concepts::ForEachFunctor;
@@ -76,6 +77,13 @@ class IterInterface
7677
template <class Second>
7778
[[nodiscard]] auto chain(Second&& it) -> Chain<T, Derived, Second>;
7879

80+
template <class Other>
81+
[[nodiscard]] auto eq(Other&& it) -> bool;
82+
83+
template <class Other, class Functor>
84+
requires EqFunctor<T, Functor>
85+
[[nodiscard]] auto eqBy(Other&& it, Functor&& f) -> bool;
86+
7987
template <class Functor>
8088
requires FilterFunctor<T, Functor>
8189
[[nodiscard]] auto filter(Functor&& f) -> Filter<T, Functor, Derived>;
@@ -244,6 +252,22 @@ auto rusty_iterators::interface::IterInterface<T, Derived>::chain(Second&& it)
244252
return Chain<T, Derived, Second>{std::forward<Derived>(self()), std::forward<Second>(it)};
245253
}
246254

255+
template <class T, class Derived>
256+
template <class Other>
257+
auto rusty_iterators::interface::IterInterface<T, Derived>::eq(Other&& it) -> bool
258+
{
259+
return self().eqBy(std::forward<Other>(it),
260+
[](auto x) { return std::get<0>(x) == std::get<1>(x); });
261+
}
262+
263+
template <class T, class Derived>
264+
template <class Other, class Functor>
265+
requires rusty_iterators::concepts::EqFunctor<T, Functor>
266+
auto rusty_iterators::interface::IterInterface<T, Derived>::eqBy(Other&& it, Functor&& f) -> bool
267+
{
268+
return self().zip(std::forward<Other>(it)).all(std::forward<Functor>(f));
269+
}
270+
247271
template <class T, class Derived>
248272
template <class Functor>
249273
requires rusty_iterators::iterator::FilterFunctor<T, Functor>
@@ -312,15 +336,15 @@ template <class R>
312336
requires rusty_iterators::concepts::Comparable<R>
313337
auto rusty_iterators::interface::IterInterface<T, Derived>::max() -> std::optional<R>
314338
{
315-
return reduce([](auto x, auto y) { return std::max(x, y); });
339+
return self().reduce([](auto x, auto y) { return std::max(x, y); });
316340
}
317341

318342
template <class T, class Derived>
319343
template <class R>
320344
requires rusty_iterators::concepts::Comparable<R>
321345
auto rusty_iterators::interface::IterInterface<T, Derived>::min() -> std::optional<R>
322346
{
323-
return reduce([](auto x, auto y) { return std::min(x, y); });
347+
return self().reduce([](auto x, auto y) { return std::min(x, y); });
324348
}
325349

326350
template <class T, class Derived>
@@ -333,7 +357,7 @@ auto rusty_iterators::interface::IterInterface<T, Derived>::movingWindow(size_t
333357
template <class T, class Derived>
334358
auto rusty_iterators::interface::IterInterface<T, Derived>::nth(size_t element) -> std::optional<T>
335359
{
336-
return advanceBy(element).next();
360+
return self().advanceBy(element).next();
337361
}
338362

339363
template <class T, class Derived>
@@ -379,7 +403,7 @@ template <class R>
379403
requires rusty_iterators::concepts::Summable<R>
380404
auto rusty_iterators::interface::IterInterface<T, Derived>::sum() -> R
381405
{
382-
return fold(R{}, [](auto acc, auto x) { return acc + x; });
406+
return self().fold(R{}, [](auto acc, auto x) { return acc + x; });
383407
}
384408

385409
template <class T, class Derived>

tests/iterator.test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,32 @@ TEST(TestIterator, TestPositionNoValueMatched)
289289

290290
ASSERT_EQ(result, std::nullopt);
291291
}
292+
293+
TEST(TestIterator, TestEqWhenSame)
294+
{
295+
auto v1 = std::vector{1, 2, 3};
296+
auto v2 = std::vector{1, 2, 3};
297+
298+
ASSERT_TRUE(LazyIterator{v1}.eq(LazyIterator{v2}));
299+
}
300+
301+
TEST(TestIterator, TestEqWhenDifferent)
302+
{
303+
auto v1 = std::vector{1, 2, 3};
304+
auto v2 = std::vector{1, 2, 4};
305+
306+
ASSERT_FALSE(LazyIterator{v1}.eq(LazyIterator{v2}));
307+
}
308+
309+
TEST(TestIterator, TestEqBy)
310+
{
311+
auto v1 = std::vector<std::string>{"a", "bc", "dea"};
312+
auto v2 = std::vector<std::string>{"j", "hg", "dfg"};
313+
314+
// Compare the vectors not by exact content, but by length of strings.
315+
auto result = LazyIterator{v1}.eqBy(LazyIterator{v2}, [](auto x) {
316+
return std::get<0>(x).get().size() == std::get<1>(x).get().size();
317+
});
318+
319+
ASSERT_TRUE(result);
320+
}

0 commit comments

Comments
 (0)