44#define BEMAN_ANY_VIEW_DETAIL_ANY_ITERATOR_HPP
55
66#include < beman/any_view/concepts.hpp>
7+ #include < beman/any_view/config.hpp>
78#include < beman/any_view/detail/intrusive_small_ptr.hpp>
89#include < beman/any_view/detail/iterator_adaptor.hpp>
910
@@ -16,23 +17,41 @@ class any_iterator {
1617 using pointer = std::add_pointer_t <RefT>;
1718
1819 using interface_type = iterator_interface<ElementT, RefT, RValueRefT, DiffT>;
20+ using cache_type =
21+ std::conditional_t <std::derived_from<IterConceptT, std::forward_iterator_tag>, iter_cache_t <RefT>, no_cache>;
22+
23+ static constexpr bool cached = not std::same_as<cache_type, no_cache>;
24+
1925 // inplace storage sufficient for a vtable pointer and two pointers
2026 intrusive_small_ptr<interface_type, 3 * sizeof (void *)> iterator_ptr;
27+ BEMAN_ANY_VIEW_NO_UNIQUE_ADDRESS () cache_type cache;
2128
2229 template <class IteratorT , class SentinelT >
2330 static consteval auto get_in_place_adaptor_type () {
2431 return std::in_place_type<
2532 detail::iterator_adaptor<ElementT, reference, rvalue_reference, DiffT, IteratorT, SentinelT>>;
2633 }
2734
35+ template <detail::any_compatible_iterator<any_iterator> IteratorT, std::sentinel_for<IteratorT> SentinelT>
36+ constexpr any_iterator (IteratorT&& iterator, SentinelT&& sentinel, cache_type&& cache)
37+ : iterator_ptr(get_in_place_adaptor_type<IteratorT, SentinelT>(), std::move(iterator), std::move(sentinel)),
38+ cache(std::move(cache)) {}
39+
2840 public:
2941 using iterator_concept = IterConceptT;
3042 using element_type = ElementT;
3143 using difference_type = DiffT;
3244
3345 template <detail::any_compatible_iterator<any_iterator> IteratorT, std::sentinel_for<IteratorT> SentinelT>
3446 constexpr any_iterator (IteratorT iterator, SentinelT sentinel)
35- : iterator_ptr(get_in_place_adaptor_type<IteratorT, SentinelT>(), std::move(iterator), std::move(sentinel)) {}
47+ : any_iterator(std::move(iterator), std::move(sentinel), cache_type()) {}
48+
49+ template <detail::any_compatible_iterator<any_iterator> IteratorT, std::sentinel_for<IteratorT> SentinelT>
50+ constexpr any_iterator (IteratorT iterator, SentinelT sentinel)
51+ requires(cached)
52+ : any_iterator(std::move(iterator),
53+ std::move(sentinel),
54+ iterator != sentinel ? iter_cache<RefT>::make(*iterator) : iter_cache_t<RefT>{}) {}
3655
3756 constexpr any_iterator () noexcept
3857 requires std::derived_from<IterConceptT, std::forward_iterator_tag>
@@ -50,7 +69,13 @@ class any_iterator {
5069
5170 constexpr any_iterator& operator =(any_iterator&&) noexcept = default ;
5271
53- [[nodiscard]] constexpr reference operator *() const { return **iterator_ptr; }
72+ [[nodiscard]] constexpr reference operator *() const {
73+ if constexpr (cached) {
74+ return *cache;
75+ } else {
76+ return **iterator_ptr;
77+ }
78+ }
5479
5580 [[nodiscard]] friend constexpr rvalue_reference iter_move (const any_iterator& other) {
5681 return other.iterator_ptr ->iter_move ();
@@ -59,11 +84,19 @@ class any_iterator {
5984 [[nodiscard]] constexpr pointer operator ->() const
6085 requires std::derived_from<IterConceptT, std::contiguous_iterator_tag>
6186 {
62- return std::to_address (*iterator_ptr);
87+ if constexpr (cached) {
88+ return cache;
89+ } else {
90+ return std::to_address (*iterator_ptr);
91+ }
6392 }
6493
6594 constexpr any_iterator& operator ++() {
66- ++*iterator_ptr;
95+ if constexpr (cached) {
96+ cache = iterator_ptr->next ();
97+ } else {
98+ ++*iterator_ptr;
99+ }
67100 return *this ;
68101 }
69102
@@ -86,7 +119,11 @@ class any_iterator {
86119 constexpr any_iterator& operator --()
87120 requires std::derived_from<IterConceptT, std::bidirectional_iterator_tag>
88121 {
89- --*iterator_ptr;
122+ if constexpr (cached) {
123+ cache = iterator_ptr->prev ();
124+ } else {
125+ --*iterator_ptr;
126+ }
90127 return *this ;
91128 }
92129
@@ -113,7 +150,11 @@ class any_iterator {
113150 constexpr any_iterator& operator +=(difference_type offset)
114151 requires std::derived_from<IterConceptT, std::random_access_iterator_tag>
115152 {
116- *iterator_ptr += offset;
153+ if constexpr (cached) {
154+ cache = iterator_ptr->next (offset);
155+ } else {
156+ *iterator_ptr += offset;
157+ }
117158 return *this ;
118159 }
119160
@@ -154,7 +195,11 @@ class any_iterator {
154195 }
155196
156197 [[nodiscard]] constexpr bool operator ==(std::default_sentinel_t sentinel) const {
157- return *iterator_ptr == sentinel;
198+ if constexpr (cached) {
199+ return cache == iter_cache_t <RefT>{};
200+ } else {
201+ return *iterator_ptr == sentinel;
202+ }
158203 }
159204};
160205
0 commit comments