Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
BidirectionalIterator.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Traversal_BidirectionalIterator_h_
5#define _Stroika_Foundation_Traversal_BidirectionalIterator_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
10
11/**
12 *
13 * \file
14 *
15 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
16 *
17 */
18
19namespace Stroika::Foundation::Traversal {
20
21 /**
22 * \brief A BidirectionalIterator is an Iterator that can be moved both forward and backward.
23 *
24 * BidirectionalIterator allows backing up (if not AtStart), and then moving forward again
25 * (if not AtEnd - like the base class Iterator).
26 *
27 * \note Satisfies Concepts:
28 * o regular<BidirectionalIterator<T>> // implies copyable/movable/equality_comparable
29 * o bidirectional_iterator<BidirectionalIterator<T>>
30 * o sentinel_for<default_sentinel_t, BidirectionalIterator<T>>
31 * o constructible_from<Iterator<T>, BidirectionalIterator<T>>
32 */
33 template <typename T, typename ITERATOR_TRAITS = Support::DefaultIteratorTraits<T>>
34 class BidirectionalIterator : public Iterator<T, ITERATOR_TRAITS> {
35 private:
37
38 public:
39 class IRep;
40
41 /*
42 * forward type declarations so can be used more easily in this definition.
43 */
44 public:
45 using difference_type = typename inherited::difference_type;
46 using value_type = typename inherited::value_type;
47 using pointer = typename inherited::pointer;
48 using reference = typename inherited::reference;
49
50 public:
51 /**
52 * \note this is used by the concept bidirectional_iterator.
53 */
54 using iterator_category = bidirectional_iterator_tag;
55
56 public:
57 /**
58 * \brief This overload is usually not called directly. Instead, iterators are
59 * usually created from a container (eg. Sequence<T>{}.begin()).
60 *
61 * Iterators are safely copyable, preserving their current position.
62 *
63 * CTOR overload taking nullptr - is the same as GetEmptyIterator ()
64 *
65 * \note default construction of BidirectionalIterator means empty (both at start and end).
66 *
67 * \pre RequireNotNull (rep.get ()) for rep-taking CTOR
68 *
69 * \note constructor with argument default_sentinel_t - creates an end iterator
70 */
71 BidirectionalIterator (const unique_ptr<IRep>& rep) noexcept;
72 BidirectionalIterator (unique_ptr<IRep>&& rep) noexcept;
73 BidirectionalIterator (BidirectionalIterator&& src) noexcept = default;
74 BidirectionalIterator (const BidirectionalIterator& src) = default;
75 constexpr BidirectionalIterator (const default_sentinel_t&) noexcept;
76 constexpr BidirectionalIterator (nullptr_t) noexcept;
77 constexpr BidirectionalIterator () noexcept;
78
79 public:
80 /**
81 * \brief Iterators are safely copyable, preserving their current position.
82 */
83 nonvirtual BidirectionalIterator& operator= (BidirectionalIterator&& rhs) noexcept = default;
84 nonvirtual BidirectionalIterator& operator= (const BidirectionalIterator& rhs) = default;
85
86 public:
87 /**
88 *
89 */
90 nonvirtual bool AtStart () const;
91
92 public:
93 /**
94 * \brief same as Iterator::operator++ () - advances iterator - but returns the subclass iterator type.
95 *
96 * The subclass impl is functionaly identical, but hiding the base class implementation needed to satisfy the concepts for bidirectional iterators.
97 */
98 nonvirtual BidirectionalIterator& operator++ ();
99 nonvirtual BidirectionalIterator operator++ (int);
100
101 public:
102 /**
103 * \pre not AtStart ()
104 */
105 nonvirtual BidirectionalIterator& operator-- ();
106 nonvirtual BidirectionalIterator operator-- (int);
107
108 public:
109 /**
110 * \brief Move the iterator back by the specified number of positions.
111 *
112 * \pre i >= 0
113 */
114 nonvirtual BidirectionalIterator operator- (ptrdiff_t i) const;
115
116 public:
117 /**
118 * \brief
119 * Get a reference to the IRep owned by the iterator. This is an implementation detail,
120 * mainly intended for implementors.
121 *
122 * Get a reference to the IRep owned by the iterator.
123 * This is an implementation detail, mainly intended for implementors.
124 */
125 nonvirtual IRep& GetRep ();
126
127 public:
128 /**
129 * \brief
130 * Get a reference to the IRep owned by the iterator. This is an implementation detail,
131 * mainly intended for implementors.
132 *
133 * Get a reference to the IRep owned by the iterator.
134 * This is an implementation detail, mainly intended for implementors.
135 */
136 nonvirtual const IRep& ConstGetRep () const;
137 };
138
139 /**
140 * \brief An Iterator<T> that also supports going backwards.
141 */
142 template <typename T, typename ITERATOR_TRAITS>
143 class BidirectionalIterator<T, ITERATOR_TRAITS>::IRep : public Iterator<T, ITERATOR_TRAITS>::IRep {
144 private:
145 using inherited = typename Iterator<T, ITERATOR_TRAITS>::IRep;
146
147 protected:
148 IRep () = default;
149
150 public:
151 /**
152 * \brief return true iff the iterator is at the start of its range. You can only backup further if NOT AtStart ()
153 *
154 * \note - if the range is empty, its BOTH AtEnd () and AtStart ()
155 */
156 virtual bool AtStart () const = 0;
157
158 public:
159 /**
160 * \brief Move iterator one position back, closer to start. Return the current value of T (which must always be valid).
161 *
162 * \pre not AtStart ()
163 */
164 virtual T Back () = 0;
165 };
166
167 // see Satisfies Concepts
168 static_assert (bidirectional_iterator<BidirectionalIterator<int>>);
169 static_assert (regular<BidirectionalIterator<int>>);
170 static_assert (sentinel_for<default_sentinel_t, BidirectionalIterator<int>>);
171 static_assert (constructible_from<Iterator<int>, BidirectionalIterator<int>>);
172
173}
174
175/*
176 ********************************************************************************
177 ******************************* Implementation Details *************************
178 ********************************************************************************
179 */
180
181#include "BidirectionalIterator.inl"
182
183#endif /*_Stroika_Foundation_Traversal_BidirectionalIterator_h_ */
An Iterator<T> that also supports going backwards.
virtual bool AtStart() const =0
return true iff the iterator is at the start of its range. You can only backup further if NOT AtStart...
virtual T Back()=0
Move iterator one position back, closer to start. Return the current value of T (which must always be...
A BidirectionalIterator is an Iterator that can be moved both forward and backward.
nonvirtual const IRep & ConstGetRep() const
Get a reference to the IRep owned by the iterator. This is an implementation detail,...
nonvirtual IRep & GetRep()
Get a reference to the IRep owned by the iterator. This is an implementation detail,...
Implementation detail for iterator implementors.
Definition Iterator.h:616
An Iterator<T> is a copyable object which allows traversing the contents of some container.
Definition Iterator.h:253
typename ITERATOR_TRAITS::difference_type difference_type
difference_type = typename ITERATOR_TRAITS::difference_type;
Definition Iterator.h:263
typename ITERATOR_TRAITS::pointer pointer
pointer = typename ITERATOR_TRAITS::pointer;
Definition Iterator.h:275
typename ITERATOR_TRAITS::value_type value_type
value_type = typename ITERATOR_TRAITS::value_type;
Definition Iterator.h:269
typename ITERATOR_TRAITS::reference reference
reference = typename ITERATOR_TRAITS::reference;
Definition Iterator.h:281