Skip to content

Commit 485ac0b

Browse files
feat: add interperse to iterator interface (#106)
1 parent 7437525 commit 485ac0b

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

include/rusty_iterators/interface.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "filter.hpp"
88
#include "filter_map.hpp"
99
#include "inspect.hpp"
10+
#include "interperse.hpp"
1011
#include "map.hpp"
1112
#include "moving_window.hpp"
1213
#include "skip.hpp"
@@ -46,6 +47,7 @@ using iterator::Enumerate;
4647
using iterator::Filter;
4748
using iterator::FilterMap;
4849
using iterator::Inspect;
50+
using iterator::Interperse;
4951
using iterator::Map;
5052
using iterator::MovingWindow;
5153
using iterator::Skip;
@@ -119,8 +121,9 @@ class IterInterface
119121

120122
template <class Functor>
121123
requires InspectFunctor<T, Functor>
122-
auto inspect(Functor&& f) -> Inspect<T, Functor, Derived>;
124+
[[nodiscard]] auto inspect(Functor&& f) -> Inspect<T, Functor, Derived>;
123125

126+
[[nodiscard]] auto interperse(T&& item) -> Interperse<T, Derived>;
124127
[[nodiscard]] auto last() -> std::optional<T>;
125128

126129
template <class Functor>
@@ -355,6 +358,13 @@ auto rusty_iterators::interface::IterInterface<T, Derived>::inspect(Functor&& f)
355358
return Inspect<T, Functor, Derived>{std::forward<Derived>(self()), std::forward<Functor>(f)};
356359
}
357360

361+
template <class T, class Derived>
362+
auto rusty_iterators::interface::IterInterface<T, Derived>::interperse(T&& item)
363+
-> Interperse<T, Derived>
364+
{
365+
return Interperse<T, Derived>{std::forward<Derived>(self()), std::forward<T>(item)};
366+
}
367+
358368
template <class T, class Derived>
359369
auto rusty_iterators::interface::IterInterface<T, Derived>::last() -> std::optional<T>
360370
{
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#pragma once
2+
3+
#include "interface.fwd.hpp"
4+
5+
#include <optional>
6+
7+
namespace rusty_iterators::iterator
8+
{
9+
using interface::IterInterface;
10+
11+
template <class T, class Other>
12+
class Interperse : public IterInterface<T, Interperse<T, Other>>
13+
{
14+
public:
15+
explicit Interperse(Other&& it, T&& item)
16+
: it(std::forward<Other>(it)), item(std::forward<T>(item))
17+
{}
18+
19+
auto next() -> std::optional<T>;
20+
[[nodiscard]] auto sizeHint() const -> std::optional<size_t>;
21+
22+
private:
23+
Other it;
24+
T item;
25+
bool interperse = false;
26+
};
27+
} // namespace rusty_iterators::iterator
28+
29+
template <class T, class Other>
30+
auto rusty_iterators::iterator::Interperse<T, Other>::next() -> std::optional<T>
31+
{
32+
if (interperse)
33+
{
34+
interperse = false;
35+
return item;
36+
}
37+
38+
auto nextItem = it.next();
39+
40+
if (!nextItem.has_value())
41+
return std::move(nextItem);
42+
43+
interperse = true;
44+
return std::move(nextItem);
45+
}
46+
47+
template <class T, class Other>
48+
auto rusty_iterators::iterator::Interperse<T, Other>::sizeHint() const -> std::optional<size_t>
49+
{
50+
auto underlyingSize = it.sizeHint();
51+
52+
if (!underlyingSize.has_value())
53+
return std::nullopt;
54+
55+
return underlyingSize.value() * 2;
56+
}

tests/interperse.test.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <gmock/gmock.h>
2+
#include <gtest/gtest.h>
3+
4+
#include <rusty_iterators/iterator.hpp>
5+
6+
using ::rusty_iterators::iterator::LazyIterator;
7+
using ::testing::ElementsAreArray;
8+
9+
TEST(TestInterperseIterator, TestNextReturnsInterpersed)
10+
{
11+
auto vec = std::vector{1, 2};
12+
13+
auto item = 5;
14+
auto it = LazyIterator{vec}.interperse(std::cref(item));
15+
16+
ASSERT_EQ(it.next(), 1);
17+
ASSERT_EQ(it.next(), 5);
18+
ASSERT_EQ(it.next(), 2);
19+
ASSERT_EQ(it.next(), 5);
20+
ASSERT_EQ(it.next(), std::nullopt);
21+
}
22+
23+
TEST(TestInterperseIterator, TestCollectReturnsAllValues)
24+
{
25+
auto vec = std::vector{1, 2, 3};
26+
27+
auto item = 5;
28+
auto it = LazyIterator{vec}.interperse(std::cref(item));
29+
30+
EXPECT_THAT(it.collect(), ElementsAreArray({1, 5, 2, 5, 3, 5}));
31+
}
32+
33+
TEST(TestInterperseIterator, TestSizeHintIsDoubled)
34+
{
35+
auto vec = std::vector{1, 2, 3};
36+
37+
auto item = 5;
38+
auto it = LazyIterator{vec}.interperse(std::cref(item));
39+
40+
ASSERT_EQ(it.sizeHint(), 6);
41+
}

0 commit comments

Comments
 (0)