11#pragma once
22
33#include " interface.fwd.hpp"
4+ #include " peekable.hpp"
45
6+ #include < algorithm>
57#include < optional>
68
79namespace rusty_iterators ::iterator
@@ -13,35 +15,38 @@ class Interperse : public IterInterface<T, Interperse<T, Other>>
1315{
1416 public:
1517 explicit Interperse (Other&& it, T&& item)
16- : it(std::forward<Other>(it)), item(std::forward<T>(item))
18+ : it(std::forward<Peekable<T, Other>> (it.peekable() )), item(std::forward<T>(item))
1719 {}
1820
1921 auto next () -> std::optional<T>;
2022 [[nodiscard]] auto sizeHint () const -> std::optional<size_t>;
2123
2224 private:
23- Other it;
25+ Peekable<T, Other> it;
2426 T item;
25- bool interperse = false ;
27+ bool returnInterperseValue = false ;
2628};
2729} // namespace rusty_iterators::iterator
2830
2931template <class T , class Other >
3032auto rusty_iterators::iterator::Interperse<T, Other>::next() -> std::optional<T>
3133{
32- if (interperse)
34+ // / NOTE: 18.01.2025 <@uncommon-nickname>
35+ // / We need to check if iterator is finished. By using a peekable
36+ // / iterator, we can do that without any significant cost, because
37+ // / we will advance the iterator anyway later.
38+ auto peeked = it.peek ();
39+
40+ [[unlikely]] if (!peeked.has_value ())
41+ return std::nullopt ;
42+
43+ if (returnInterperseValue)
3344 {
34- interperse = false ;
45+ returnInterperseValue = false ;
3546 return item;
3647 }
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);
48+ returnInterperseValue = true ;
49+ return std::move (it.next ());
4550}
4651
4752template <class T , class Other >
@@ -52,5 +57,7 @@ auto rusty_iterators::iterator::Interperse<T, Other>::sizeHint() const -> std::o
5257 if (!underlyingSize.has_value ())
5358 return std::nullopt ;
5459
55- return underlyingSize.value () * 2 ;
60+ int32_t potentialSize = (underlyingSize.value () * 2 ) - 1 ;
61+
62+ return std::max (0 , potentialSize);
5663}
0 commit comments