Skip to content

Commit 7437525

Browse files
feat: add product to iterator interface (#107)
* feat: add product to iterator interface * fix: adapt lazy iterator to work with product
1 parent 7d7c429 commit 7437525

4 files changed

Lines changed: 49 additions & 1 deletion

File tree

include/rusty_iterators/concepts.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ concept InspectFunctor = requires(Functor f, T& t) {
6060
template <class T, class Functor>
6161
concept PositionFunctor = AllFunctor<T, Functor>;
6262

63+
template <class T>
64+
concept Multiplyable = requires(T first, T second) {
65+
{ first* second } -> std::same_as<T>;
66+
};
67+
6368
template <class T, class Functor>
6469
concept ReduceFunctor = FoldFunctor<T, T, Functor>;
6570

include/rusty_iterators/interface.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ using concepts::FoldFunctor;
3030
using concepts::ForEachFunctor;
3131
using concepts::Indexable;
3232
using concepts::InspectFunctor;
33+
using concepts::Multiplyable;
3334
using concepts::NeFunctor;
3435
using concepts::PositionFunctor;
3536
using concepts::ReduceFunctor;
@@ -149,6 +150,10 @@ class IterInterface
149150
requires PositionFunctor<T, Functor>
150151
[[nodiscard]] auto position(Functor&& f) -> std::optional<size_t>;
151152

153+
template <class R = T>
154+
requires Multiplyable<R>
155+
[[nodiscard]] auto product() -> std::optional<R>;
156+
152157
template <class Functor>
153158
requires ReduceFunctor<T, Functor>
154159
[[nodiscard]] auto reduce(Functor&& f) -> std::optional<T>;
@@ -434,6 +439,14 @@ auto rusty_iterators::interface::IterInterface<T, Derived>::position(Functor&& f
434439
return std::nullopt;
435440
}
436441

442+
template <class T, class Derived>
443+
template <class R>
444+
requires rusty_iterators::concepts::Multiplyable<R>
445+
auto rusty_iterators::interface::IterInterface<T, Derived>::product() -> std::optional<R>
446+
{
447+
return self().reduce([](auto acc, auto x) { return acc * x; });
448+
}
449+
437450
template <class T, class Derived>
438451
template <class Functor>
439452
requires rusty_iterators::concepts::ReduceFunctor<T, Functor>

include/rusty_iterators/iterator.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using Item = std::reference_wrapper<const typename Container::value_type>;
1616
namespace rusty_iterators::iterator
1717
{
1818
using concepts::FoldFunctor;
19+
using concepts::Multiplyable;
1920
using concepts::Summable;
2021

2122
template <class Container>
@@ -32,6 +33,10 @@ class LazyIterator : public interface::IterInterface<Item<Container>, LazyIterat
3233
auto next() -> std::optional<T>;
3334
[[nodiscard]] auto sizeHint() const -> std::optional<size_t>;
3435

36+
template <class R = RawT>
37+
requires Multiplyable<R>
38+
[[nodiscard]] auto product() -> std::optional<R>;
39+
3540
template <class R = RawT>
3641
requires Summable<R>
3742
[[nodiscard]] auto sum() -> R;
@@ -62,11 +67,20 @@ auto rusty_iterators::iterator::LazyIterator<Container>::sizeHint() const -> std
6267
return end - ptr;
6368
}
6469

70+
template <class Container>
71+
requires std::ranges::range<Container>
72+
template <class R>
73+
requires rusty_iterators::concepts::Multiplyable<R>
74+
auto rusty_iterators::iterator::LazyIterator<Container>::product() -> std::optional<R>
75+
{
76+
return this->map([](auto x) { return x.get(); }).product();
77+
}
78+
6579
template <class Container>
6680
requires std::ranges::range<Container>
6781
template <class R>
6882
requires rusty_iterators::concepts::Summable<R>
6983
auto rusty_iterators::iterator::LazyIterator<Container>::sum() -> R
7084
{
71-
return this->fold(RawT{}, [](auto acc, auto x) { return acc + x; });
85+
return this->map([](auto x) { return x.get(); }).sum();
7286
}

tests/iterator.test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,19 @@ TEST(TestIterator, TestLast)
379379

380380
ASSERT_EQ(it.last(), 3);
381381
}
382+
383+
TEST(TestIterator, TestLazyIteratorProduct)
384+
{
385+
auto vec = std::vector{1, 2, 3, 4};
386+
auto it = LazyIterator{vec};
387+
388+
ASSERT_EQ(it.product(), 1 * 2 * 3 * 4);
389+
}
390+
391+
TEST(TestIterator, TestProductOnMapIterator)
392+
{
393+
auto vec = std::vector{1, 2, 3, 4};
394+
auto it = LazyIterator{vec}.map([](auto x) { return x * 2; });
395+
396+
ASSERT_EQ(it.product(), 2 * 4 * 6 * 8);
397+
}

0 commit comments

Comments
 (0)