Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
DiscreteRange.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_DiscreteRange_h_
5#define _Stroika_Foundation_Traversal_DiscreteRange_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
11
12/**
13 * \file
14 *
15 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
16 *
17 * TODO:
18 * @todo Consider if clearer having DiscreteRange aggregate Elements() instead of inheriting from
19 * Iterable. Would make construction, and coipying etc cheaper (esp when that feature
20 * is not used).
21
22
23 >>>> DOCUMENT WHY DsicreateRange<> no longer Iterabkle<?>
24 >>> avoids conflict on empty, and provides clearer 'getlength'.
25 >>> avoids shared_ptr stuff (REP) for iterablke unles/until used.
26 >>> this should allow constexpr discrete_rage!!!
27 >>> and see other comments on why - in progress switchover...
28 >>> (NOTE - downside is
29 - for (auto i : DiscreteRange<Color> (optional<Color> (), optional<Color> ())) {
30 + for (auto i : DiscreteRange<Color> (optional<Color> (), optional<Color> ()).Elements ()) {
31
32
33 *
34 * @todo Understand what you must do DiscreteRange<int> (1,10) instead of just DiscreteRange (1,10),
35 * and if something reasonable to be done about it - do so (compiler bug or ambiguity due to optional)
36 * or just that template inference of types doesn't work as well as I thought...
37 *
38 * @todo Try to rewrite using Generator<> code... See if that simplifies things...
39 */
40
41namespace Stroika::Foundation::Traversal {
42
43 /**
44 * \brief requirements for 'T' to use DiscreteRange<T>: same as IRangeable<T> - because the 'discrete' part is handled via TRAITS.
45 *
46 * \todo - should this require GetNext/GetPrevious? - API CURRENTLY DOES --LGP 2026-02-23, which doesnt always make sense. COULD move that to
47 * DISCRETE TRAITS/DISCRETE Range???
48 */
49 template <typename T>
51
52 /**
53 * Same as Range traits requirements, but MUST support GetNext/GetPrevious, and must be CLOSED.
54 */
55 template <typename TRAITS, typename T>
57 TRAITS::kLowerBoundOpenness == Openness::eClosed and TRAITS::kUpperBoundOpenness == Openness::eClosed;
58
59 /**
60 * \brief A DiscreteRange is a Range where the underlying endpoints are integral (discrete, not continuous);
61 * this implies you can iterate over the members of the range, and its endpoints are closed.
62 *
63 * DiscreteRange<> is an immutable type (once constructed, will never change), except for allowing operator=..
64 *
65 * \par Example Usage
66 * \code
67 * vector<int> v = DiscreteRange<int>{1,10}.Elements ().As<vector<int>> ();
68 * // equiv to vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
69 * \endcode
70 *
71 * \par OR
72 * \code
73 * for (auto i : DiscreteRange<int>{1,10}) {
74 * ...i = 1..10
75 * }
76 * \endcode
77 *
78 * \par OR
79 * \code
80 * enum class Color { red, blue, green, Stroika_Define_Enum_Bounds (red, green) };
81 * for (auto i : DiscreteRange<Color>::FullRange ().Elements ()) {
82 * // iterate over each color - red, green, blue
83 * }
84 * \endcode
85 *
86 * \note Since the default traits for an enum with Stroika type annotation (Stroika_Define_Enum_Bounds)
87 * provides the start/end, DiscreteRange<SOME_ENUM>::FullRange ().Elements () returns an
88 * iterable with all possible legal values of the enum.
89 */
90 template <IDiscreteRangeable T, IDiscreteRangeableTraits<T> TRAITS = RangeTraits::Default<T>>
91 class DiscreteRange : public Range<T, TRAITS> {
92 private:
94
95 public:
96 /**
97 */
98 using value_type = typename inherited::value_type;
99
100 public:
101 /**
102 */
103 using SignedDifferenceType = typename inherited::SignedDifferenceType;
104
105 public:
106 /**
107 */
108 using UnsignedDifferenceType = typename inherited::UnsignedDifferenceType;
109
110 private:
111 struct MyIteratorRep_;
112
113 public:
114 /**
115 * DiscreteRange () with no arguments produces an empty sequence.
116 *
117 * \pre begin <= end (after substitution of optional values)
118 * \pre src range must be eClosed on both sides
119 */
120 explicit constexpr DiscreteRange () = default;
121 explicit constexpr DiscreteRange (T begin, T end);
122 explicit constexpr DiscreteRange (const optional<T>& begin, const optional<T>& end);
123 explicit constexpr DiscreteRange (const Range<T, TRAITS>& r);
124
125 public:
126 /**
127 * Like Range<>::FullRange () but returning a DiscreteRange<> type.
128 */
129 static constexpr DiscreteRange FullRange ();
130
131 public:
132 /**
133 * Like Range<>::Intersection (), but returning a DiscreteRange<> type.
134 */
135 constexpr Range<T, TRAITS> Intersection (const Range<T, TRAITS>& rhs) const;
136 constexpr DiscreteRange Intersection (const DiscreteRange& rhs) const;
137
138 public:
139 /**
140 * Like Range<>::UnionBounds (), but returning a DiscreteRange<> type.
141 */
142 constexpr Range<T, TRAITS> UnionBounds (const Range<T, TRAITS>& rhs) const;
143 constexpr DiscreteRange UnionBounds (const DiscreteRange& rhs) const;
144
145 public:
146 /**
147 * This returns the number of points from lower bound to upper bound inclusive.
148 * This equals GetDistanceSpanned () + 1 (roughly).
149 * If (empty ()) .... this returns 0;
150 */
151 constexpr UnsignedDifferenceType GetNumberOfContainedPoints () const;
152
153 public:
154 /**
155 * \pre not empty
156 * \pre the DiscreteRange produced by applying the given offset to *this remains valid with respect to the constraints on this DiscreteRange.
157 */
158 constexpr DiscreteRange Offset (SignedDifferenceType o) const;
159
160 public:
161 /**
162 * \par Example Usage
163 * \code
164 * DisjointDiscreteRange<DiscreteRange<int>> t;
165 * for (T i : t.Elements ()) {
166 * }
167 * \endcode
168 *
169 * Elements () makes no guarantees about whether or not modifications to the underlying DisjointDiscreteRange<> will
170 * appear in the Elements() Iterable<T>.
171 *
172 * \note Elements produces a generator, not an actual list of each item (internally). This should not be visible externally,
173 * except in how much memory or time is required to create an Elements() iterable for a large range (should be cheap).
174 */
175 nonvirtual Iterable<T> Elements () const;
176
177 public:
178 /**
179 * @aliases Elements ()
180 */
181 nonvirtual operator Iterable<T> () const;
182
183 public:
184 /**
185 * \see Elements () - this produces a generator iterator, so should be quite cheap even for a large range.
186 */
187 nonvirtual Iterator<T> begin () const;
188
189 public:
190 /**
191 */
192 nonvirtual Iterator<T> end () const;
193
194 private:
195 struct MyIterable_;
196 };
197
198 /**
199 */
200 template <typename RANGE_TYPE>
201 concept IDiscreteRange = derived_from<RANGE_TYPE, DiscreteRange<typename RANGE_TYPE::value_type, typename RANGE_TYPE::TraitsType>>;
202
203 /**
204 * Intersection ()
205 */
206 template <IDiscreteRangeable T, IDiscreteRangeableTraits<T> TRAITS>
208
209}
210
211/*
212 ********************************************************************************
213 ******************************* Implementation Details *************************
214 ********************************************************************************
215 */
216#include "DiscreteRange.inl"
217
218#endif /*_Stroika_Foundation_Traversal_DiscreteRange_h_ */
A DiscreteRange is a Range where the underlying endpoints are integral (discrete, not continuous); th...
constexpr Range< T, TRAITS > Intersection(const Range< T, TRAITS > &rhs) const
nonvirtual Iterator< T > begin() const
nonvirtual Iterable< T > Elements() const
constexpr Range< T, TRAITS > UnionBounds(const Range< T, TRAITS > &rhs) const
constexpr UnsignedDifferenceType GetNumberOfContainedPoints() const
static constexpr DiscreteRange FullRange()
constexpr DiscreteRange Offset(SignedDifferenceType o) const
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
An Iterator<T> is a copyable object which allows traversing the contents of some container....
Definition Iterator.h:225
T value_type
Range::value_type is the type of the contained elements of the range (say range of integers,...
Definition Range.h:309
requirements for 'T' to use Range<T>.
Definition Range.h:255
requirements for 'T' to use DiscreteRange<T>: same as IRangeable<T> - because the 'discrete' part is ...
requirements for 'T' to use Range<T>.
Definition Range.h:45