Stroika Library 3.0d21
 
Loading...
Searching...
No Matches
Range.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Traversal_Range_h_
5#define _Stroika_Foundation_Traversal_Range_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <limits>
10#include <optional>
11#include <type_traits>
12
15#include "Stroika/Foundation/Common/Common.h"
18
19/**
20 * \file
21 *
22 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
23 *
24 * \em Design Note
25 * This module was inspired by Ruby Range class, but in the end, it was mostly based on HealthFrame's
26 * DateRangeType/DateTimeRangeType code.
27 *
28 * This notion of 'range' has VERY LITTLE todo with the std::range feature (which is more like Stroika 'Iterable')
29 *
30 * TODO:
31 * @todo Better integrate with http://stroika-bugs.sophists.com/browse/STK-779 - C++20 ranges library
32 *
33 * @todo Carefully review intersection/union bounds code for new open/closed parameters. Either make sure
34 * it works or at least more carefully document in method headers the quirks of the
35 * chosen definition.
36 */
37
38namespace Stroika::Foundation::Traversal {
39
40 /**
41 * \note - ALL these RangeTraits helper classes use template <> struct instead of template<> using because
42 * as of C++17, you cannot do template specialization of using templates (otherwise using would be better)
43 */
44 namespace RangeTraits {
45
46 /**
47 * \note really just used to construct Explicit<> or ExplicitOpennessAndDifferenceType<>
48 */
49 template <typename DIFFERENCE_TYPE, typename UNSIGNED_DIFFERENCE_TYPE = Common::UnsignedOfIf<DIFFERENCE_TYPE>>
51 using SignedDifferenceType = DIFFERENCE_TYPE;
52 using UnsignedDifferenceType = UNSIGNED_DIFFERENCE_TYPE;
53 };
54
55 /**
56 * \note really just used to construct Explicit<> or ExplicitOpennessAndDifferenceType<>
57 */
58 template <typename T>
59 struct DefaultDifferenceTypes : ExplicitDifferenceTypes<Common::DifferenceType<T>> {};
60
61 /**
62 * \note really just used to construct Explicit<> or ExplicitOpennessAndDifferenceType<>
63 */
64 template <Openness LOWER_BOUND, Openness UPPER_BOUND>
66 static constexpr Openness kLowerBound{LOWER_BOUND};
67 static constexpr Openness kUpperBound{UPPER_BOUND};
68 };
69
70 /**
71 * \brief This defines the default openness for a given type T, except for specializaitons. This is used
72 * by Explict<>, and indirectly by Range<> itself.
73 * Generally its eClosed, by default, except for the upper bound on floating point Ranges.
74 * The reason for this exception on floating point, is that its often helpful to have a series of
75 * ranges that form a partition, and that works out more easily with half-open intervals.
76 *
77 * \note really just used to construct Explicit<> or ExplicitOpennessAndDifferenceType<>
78 */
79 template <typename T>
81 : conditional_t<is_floating_point_v<T>, ExplicitOpenness<Openness::eClosed, Openness::eOpen>, ExplicitOpenness<Openness::eClosed, Openness::eClosed>> {
82 };
83
84 /**
85 * \note really just used to construct Explicit<>
86 *
87 * Sadly this doesn't work for floating point types, so you must declare your own class with kLowerBounds and kUpperBounds, and pass its
88 * type.
89 *
90 * https://stackoverflow.com/questions/2183087/why-cant-i-use-float-value-as-a-template-parameter
91 *
92 * More confusingly, this limitation, though part of the C++ standard, only appears to be enforced by gcc/clang compilers, and
93 * not MSVC (as of 2020-12-11)
94 */
95 template <typename T, T MIN, T MAX>
97 static constexpr T kLowerBound{MIN};
98 static constexpr T kUpperBound{MAX};
99 };
100
101 /**
102 * \note really just used to construct Explicit<>
103 *
104 * \note implementation of DefaultBounds<> cannot use ExplicitBounds<> because that wont work with floating point types
105 */
106 template <typename T>
108 static constexpr T kLowerBound{numeric_limits<T>::lowest ()};
109 static constexpr T kUpperBound{numeric_limits<T>::max ()};
110 };
111
112 /**
113 * The ONLY reason this exists (as opposed to just Explicit<> is because we cannot create templates taking arguments
114 * of BOUNDS sometimes (because the VALUES MIN/MAX cannot be used as template parameters).
115 */
116 template <typename T, typename OPENNESS = DefaultOpenness<T>, typename DIFF_TYPE = DefaultDifferenceTypes<T>>
118 using value_type = T;
119 using SignedDifferenceType = typename DIFF_TYPE::SignedDifferenceType;
120 using UnsignedDifferenceType = typename DIFF_TYPE::UnsignedDifferenceType;
121
122 static constexpr Openness kLowerBoundOpenness{OPENNESS::kLowerBound};
123 static constexpr Openness kUpperBoundOpenness{OPENNESS::kUpperBound};
124
125 /**
126 * Compute the difference between two elements of type T for the Range (RHS - LHS)
127 */
128 static constexpr SignedDifferenceType Difference (Common::ArgByValueType<value_type> lhs, Common::ArgByValueType<value_type> rhs);
129
130 // Must be able to convert the underlying 'T' difference type to size_t sometimes
131 static size_t DifferenceToSizeT (UnsignedDifferenceType s)
132 {
133 return size_t (s);
134 }
135 static size_t DifferenceToSizeT (SignedDifferenceType s)
136 requires (not same_as<UnsignedDifferenceType, SignedDifferenceType>)
137 {
138 return size_t (s);
139 }
140 };
141
142 /**
143 * \note Only used to construct/define a specific Range<> type
144 *
145 * Explicit<> can be used to specify inline (type) all the details for the range functionality
146 * for a given type T. Also, it provides often usable default implementations of things like GetNext, GetPrevious ().
147 */
148 template <typename T, typename OPENNESS = DefaultOpenness<T>, typename BOUNDS = DefaultBounds<T>, typename DIFF_TYPE = DefaultDifferenceTypes<T>>
149 struct Explicit : ExplicitOpennessAndDifferenceType<T, OPENNESS, DIFF_TYPE> {
151 using value_type = T;
152 //using value_type = typename inherited::value_type; // @todo debug why this doesn't work!
153 using SignedDifferenceType = typename inherited::SignedDifferenceType;
154 using UnsignedDifferenceType = typename inherited::UnsignedDifferenceType;
155
156 static constexpr T kLowerBound{BOUNDS::kLowerBound};
157 static constexpr T kUpperBound{BOUNDS::kUpperBound};
158
159 /**
160 * Return the Next possible value.
161 *
162 * \pre arg != last-possible-value
163 *
164 * \note its hard todo GetNext() for floating point as constexpr because underlying function in cmath not yet constexpr (as of C++17)
165 */
166 static constexpr value_type GetNext (value_type i)
167 requires (is_integral_v<T> or is_enum_v<T>);
168 static value_type GetNext (value_type i)
169 requires (is_floating_point_v<T>);
170
171 /**
172 * Return the Previous possible value.
173 *
174 * \pre arg != first-possible-value
175 *
176 * \note its hard todo GetPrevious() for floating point as constexpr because underlying function in cmath not yet constexpr (as of C++17)
177 */
178 static constexpr value_type GetPrevious (value_type i)
179 requires (is_integral_v<T> or is_enum_v<T>);
180 static value_type GetPrevious (value_type i)
181 requires (is_floating_point_v<T>);
182 };
183
184 /**
185 * \note Only used to construct/define a specific Range<> type
186 */
187 template <typename T>
188 struct Default_Integral : Explicit<T, ExplicitOpenness<Openness::eClosed, Openness::eClosed>> {};
189
190 /**
191 * \note Only used to construct/define a specific Range<> type
192 *
193 * Default_Enum<> can be used to generate an automatic traits object (with bounds)
194 * if you've applied the Stroika_Define_Enum_Bounds() macro to the given enumeration.
195 */
196 template <typename T>
197 struct Default_Enum : Explicit<T, ExplicitOpenness<Openness::eClosed, Openness::eClosed>, ExplicitBounds<T, T::eSTART, T::eLAST>> {};
198
199 /**
200 * \note Only used to construct/define a specific Range<> type
201 *
202 * This defaults to a half-open (lhs closed, rhs-open) range, and should work for any arithmetic type
203 * (where you can subtract elements, etc)
204 */
205 template <typename T>
206 struct Default_Arithmetic : Explicit<T, ExplicitOpenness<Openness::eClosed, Openness::eOpen>> {};
207
208 /**
209 * Default<> contains the default traits used by a Range<> class. For most builtin types, this will
210 * be fine. For many Stroika types, specializations exist, so that you can just use Range<T> directly.
211 *
212 * But you may find it handy to define your own Range 'traits' object.
213 *
214 * \note The default OPENNESS for Default varies by TYPE T. Integer and enums are both
215 * fully closed by default, and other arithmetic types (floats) are half open [)
216 *
217 * \note Would be nice to use using syntax and not introduce a new type, but apparently
218 * using declarations cannot be specialized in C++17 (@todo add reference)
219 */
220 template <typename T>
221 struct Default
222 : conditional_t<is_enum_v<T>, Common::LazyType_t<Default_Enum, T>,
223 conditional_t<is_integral_v<T>, Common::LazyType_t<Default_Integral, T>,
224 conditional_t<is_arithmetic_v<T> or true, Common::LazyType_t<Default_Arithmetic, T>, void>>> {};
225
226 }
227
228 template <typename T, typename RANGE_TYPE>
229 class DisjointRange;
230
231 /**
232 * A Range<> is analogous to a mathematical range. It's left and and its right sides can
233 * be optionally open or closed.
234 *
235 * Range<> is an immutable type (once constructed, will never change), except for allowing operator=.
236 *
237 * A range always has a lower and upper bound (if not specified in CTOR, its specified by the type traits) so no
238 * unbounded ranges).
239 *
240 * For a range to contain a single point, min=max, and both sides must be closed (else its a require error)
241 *
242 * This Range<> template is similar to Ruby range, and fairly DIFFERENT from the std::range<> template.
243 *
244 * This notion of range is **NOT THE SAME as std::range**, though is similar (obviously from the name).
245 *
246 * Somewhat inspired by, and at least influenced by, the definition in
247 * http://ruby-doc.org/core-2.0/Range.html
248 * However - where Ruby has one type "Range" - we have "Range" and DiscreteRange" - and some ruby Range methods/properties
249 * are expressed only in DiscreteRange<>. Also Stroika Range has openness as an optional/configurable
250 * feature of both endpoints, whereas in Ruby, the LHS is always closed and its RHS is optionally open.
251 *
252 * Note - you can do Range<float>, but cannot do DiscreteRange<float> - but can do DiscreteRange<int>.
253 *
254 * A note about an empty range. All empty ranges (of the same type) are equal to one another. It is illegal
255 * to ask for the start or end of an empty range. Empty ranges contain no points.
256 *
257 * It is illegal to call:
258 * Range<int>{1,1, Openness::eOpen, Openness::eOpen} since this would produce an empty range.
259 *
260 * Range<int>{1,1, Openness::eClosed, Openness::eClosed} != Range<int>{3,3, Openness::eClosed, Openness::eClosed}
261 * would be true, since neither is empty and they contain different points (1 vs 3).
262 *
263 * \note The default OPENNESS for Default varies by TYPE T. Integer and enums are both
264 * fully closed by default, and other arithmetic types (floats) are half open [)
265 *
266 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
267 * o Standard Stroika Comparison support (operator==, operator<=>, etc);
268 * o Depends on operator==/operator<=> being defined on T
269 *
270 * @see DiscreteRange
271 * @see DisjointRange
272 * @see DisjointDiscreteRange
273 */
274 template <typename T, typename TRAITS = RangeTraits::Default<T>>
275 class Range {
276 public:
277 /**
278 * \brief Range::value_type is the type of the contained elements of the range (say range of integers, value_type=int)
279 */
280 using value_type = T;
281
282 public:
283 /**
284 */
285 using TraitsType = TRAITS;
286
287 public:
288 /**
289 */
290 using SignedDifferenceType = typename TraitsType::SignedDifferenceType;
291
292 public:
293 /**
294 */
295 using UnsignedDifferenceType = typename TraitsType::UnsignedDifferenceType;
296
297 public:
298 /**
299 * Range{} creates an empty range (note all empty () ranges of the same type are equal to each other).
300 *
301 * optional values - if omitted - are replaced with the TRAITS::kLowerBound and TRAITS::kUpperBound values (as well as 'TRAITs' default openness).
302 * Constructors with actual numeric values (begin/end) MUST construct non-empty ranges (begin == end ==> both sides closed).
303 *
304 * \pre begin <= end (after substitution of optional values)
305 * \pre begin < end or LHS/RHS CLOSED (after substitution of optional values)
306 *
307 * \par Example Usage
308 * \code
309 * Range<double> r1{3, 5};
310 * Assert (r1.Contains (3) and not r1.Contains (3)); // because default arithmetic traits have [) half open
311 * Range<double> r2{ 3, 5, Openness::eOpen, Openness::eOpen };
312 * Assert (not r2.Contains (3));
313 * \endcode
314 */
315 constexpr explicit Range ();
316 template <typename T2, typename TRAITS2>
317 constexpr explicit Range (const Range<T2, TRAITS>& src);
318 constexpr explicit Range (Common::ArgByValueType<T> begin, Common::ArgByValueType<T> end);
319 constexpr explicit Range (const optional<T>& begin, const optional<T>& end);
320 constexpr explicit Range (Common::ArgByValueType<T> begin, Common::ArgByValueType<T> end, Openness lhsOpen, Openness rhsOpen);
321 constexpr explicit Range (const optional<T>& begin, const optional<T>& end, Openness lhsOpen, Openness rhsOpen);
322
323 public:
324 /**
325 * \brief Construct a new Range from this, but with the given start
326 * \pre start <= GetUpperBound ()
327 */
328 constexpr Range ReplaceStart (Common::ArgByValueType<T> start) const;
329
330 public:
331 /**
332 * \brief Construct a new Range from this, but with the given end
333 * \pre GetLowerBound () <= end
334 */
335 constexpr Range ReplaceEnd (Common::ArgByValueType<T> end) const;
336
337 public:
338 /**
339 * \brief returns a range centered around center, with the given radius (and optionally argument openness).
340 */
342 Openness lhsOpen = TRAITS::kLowerBoundOpenness, Openness rhsOpen = TRAITS::kUpperBoundOpenness);
343
344 public:
345 /**
346 * This returns begin>end? EMPTY else Range<T, TRAITS> (begin, end);
347 *
348 * The Range(begin/end) CTOR REQUIRES begin<=end). This does not, and just produces an empty range in that case.
349 */
351
352 public:
353 /**
354 * This returns Range{
355 * TraitsType::kLowerBound, TraitsType::kUpperBound,
356 * TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
357 * };
358 */
359 static constexpr Range FullRange ();
360
361 public:
362 /**
363 * A Range is considered empty if it contains no points. If GetLowerBound () < GetUpperBound (),
364 * then clearly this is non-empty. If created with Range/0() - then the range this is empty.
365 *
366 * But if GetLowerBound () == GetUpperBound () - this is a trickier case. With both ends CLOSED -
367 * that means the GetLowerBound () value is contained in the range, so that is not empty.
368 *
369 * if GetLowerBound () == GetUpperBound (), and both ends open, then there are no points contained.
370 *
371 * But if GetLowerBound () == GetUpperBound (), and one one side is open, and the other closed,
372 * the one closed point endpoint is in the range, so the range is non-empty.
373 */
374 constexpr bool empty () const;
375
376 public:
377 /**
378 * \brief equivalent to not this->empty ();
379 */
380 constexpr explicit operator bool () const;
381
382 public:
383 /**
384 * GetUpperBound ()-GetLowerBound (), or distance from GetLowerBound () to end of the range.
385 * If this is empty (), then GetDistanceSpanned () will be zero but the GetDistanceSpanned CAN be zero without the
386 * range being empty (if both ends are closed).
387 *
388 * \note this just uses TraitsType::Difference ()
389 *
390 * \note For discrete Ranges, this does NOT correspond to the number of points (this is one less)
391 */
392 constexpr UnsignedDifferenceType GetDistanceSpanned () const;
393
394 public:
395 /**
396 * \pre not empty ()
397 */
398 constexpr T GetMidpoint () const;
399
400 public:
401 /**
402 * Compare v with the upper and lower bounds of this range, and return a value as close as
403 * possible to v but in range.
404 *
405 * If 'v' is not in range, and this Range is open, GetNext or GetPrevious maybe used to find a value
406 * in range.
407 *
408 * \pre not empty ()
409 *
410 * @see std::clamp
411 */
412 constexpr T Pin (T v) const;
413
414 public:
415 /**
416 * This corresponds to the mathematical set containment. When comparing with the edges
417 * of the range, we check <= if the edge is closed, and < if the edge is open.
418 */
419 constexpr bool Contains (Common::ArgByValueType<T> r) const;
420 constexpr bool Contains (const Range& containee) const;
421
422 public:
423 /**
424 * Returns an identical Range to this, but including its end points.
425 *
426 * \pre not empty ();
427 */
428 nonvirtual constexpr Range Closure () const;
429
430 public:
431 /**
432 * \note All empty ranges (of the same type) are equal to each other.
433 */
434 constexpr bool operator== (const Range& rhs) const;
435
436 public:
437 /**
438 */
439 constexpr partial_ordering operator<=> (const Range& rhs) const;
440
441 public:
442 /**
443 * \brief Compute a less-like notion for Range.
444 *
445 * There is no clear way to provide an ordering of two ranges (of the same type). The ordering of their
446 * left sides, may not agree with the ordering of their right sides, or their midpoints.
447 *
448 * But - OFTEN - they CAN be ordered! And that's often a useful concept. So capture that case at least.
449 * Just return nullopt if not comparable. Then the caller can decide how to break the 'tie' - with midpoint compare, or
450 * left or right edge compares...
451 */
452 [[deprecated ("USE operator<==> - check <=> produces less (vs unordered) ")]] constexpr optional<bool> DefinitelyLessThan (const Range& rhs) const
453 {
454 return (*this <=> rhs) == partial_ordering::less;
455 }
456
457 public:
458 /**
459 * Returns true iff there are any points shared in common between this range and the rhs range.
460 *
461 * \par Example Usage
462 * \code
463 * using RT = Range<int>;
464 * constexpr auto eOpen = Openness::eOpen;
465 * constexpr auto eClosed = Openness::eClosed;
466 * Assert ((RT{1, 2}.Intersects (RT{1, 2})));
467 * Assert ((not RT{1, 2, eOpen, eOpen}.Intersects (RT{2, 3, eOpen, eOpen})));
468 * Assert ((not RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eOpen, eOpen})));
469 * Assert ((RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eClosed, eOpen})));
470 * \endcode
471 *
472 * \see operator^
473 */
474 template <typename T2, typename TRAITS2>
475 constexpr bool Intersects (const Range<T2, TRAITS2>& rhs) const;
476
477 public:
478 /**
479 * Compute the overlap/intersection between two ranges. The resulting range defines exactly the points in both places (so respects openness).
480 *
481 * @see operator^ - an operator alias for this function
482 */
483 constexpr Range Intersection (const Range& rhs) const;
484
485 public:
486 /**
487 * if two regions are disjoint, this can encompass a larger region than the actual union would
488 */
489 nonvirtual DisjointRange<T, Range> Union (const Range& rhs) const;
490
491 public:
492 /**
493 * if two regions are disjoint, this can encompass a larger region than the actual union would
494 *
495 * \note See also Extend ();
496 * \note See also Union ();
497 */
498 constexpr Range UnionBounds (const Range& rhs) const;
499
500 public:
501 /**
502 * Construct a new range from this range, but including the given point
503 * Note that can produce a range with different openness from the starting range (as the points added close the endpoints).
504 *
505 * \note See also UnionBounds ();
506 */
507 constexpr Range Extend (Common::ArgByValueType<T> value) const;
508
509 public:
510 /**
511 * \pre not empty (); // special case - no upper/lower bound
512 */
513 constexpr T GetLowerBound () const;
514
515 public:
516 /**
517 */
518 constexpr Openness GetLowerBoundOpenness () const;
519
520 public:
521 /**
522 * \pre not empty (); // special case - no upper/lower bound
523 */
524 constexpr T GetUpperBound () const;
525
526 public:
527 /**
528 */
529 constexpr Openness GetUpperBoundOpenness () const;
530
531 public:
532 /**
533 * \pre not empty
534 * \pre the Range produced by applying the given offset to *this remains valid with respect to the constraints on this Range.
535 */
536 constexpr Range Offset (SignedDifferenceType o) const;
537
538 public:
539 /**
540 * \pre not empty
541 * \pre the Range produced by applying the given factor to the upper and lower bounds.
542 * \pre T has operator* (T,T) -> T defined
543 */
544 constexpr Range Times (T o) const;
545
546 public:
547 /**
548 * Print a displayable rendition of the given range, using the argument function to format
549 * the basic value_type.
550 *
551 * \par Example Usage
552 * \code
553 * Assert (Range<int>{3, 4}.ToString () == "[3 ... 4)");
554 * Assert (Range<int>{3, 4}.ToString ([] (int n) { return "{}"_f (n); }) == "[3 ... 4)");
555 * \endcode
556 *
557 * if the 'UpperBound' == kUpperBound, its not shown
558 *
559 * \par Example Usage
560 * \code
561 * Assert (Range<int>{3, nullopt}.ToString () == "[3 ... ]");
562 * \endcode
563 *
564 * Similarly for (only) LowerBound == kLowerBound
565 *
566 * \par Example Usage
567 * \code
568 * Assert (Range<int>{nullopt, 4}.ToString () == "[ ... 4]");
569 * \endcode
570 * @see Characters::ToString ();
571 */
572 nonvirtual Characters::String ToString (const function<Characters::String (const T&)>& elt2String = [] (const T& x) -> Characters::String {
573 return Characters::ToString (x);
574 }) const;
575
576 private:
577 T fBegin_;
578 T fEnd_;
579 Openness fBeginOpenness_;
580 Openness fEndOpenness_;
581 };
582
583 /**
584 */
585 template <typename RANGE_TYPE>
586 concept IRange = derived_from<RANGE_TYPE, Range<typename RANGE_TYPE::value_type, typename RANGE_TYPE::TraitsType>>;
587
588 /**
589 * Alias: T + RANGE => RANGE.Offset(T)
590 * Alias: RANGE + RANGE => RANGE.Union (RANGE)
591 */
592 template <typename T, typename TRAITS>
593 constexpr Range<T, TRAITS> operator+ (const T& lhs, const Range<T, TRAITS>& rhs);
594 template <typename T, typename TRAITS>
595 constexpr Range<T, TRAITS> operator+ (const Range<T, TRAITS>& lhs, const T& rhs);
596 template <typename T, typename TRAITS>
597 DisjointRange<T, Range<T, TRAITS>> operator+ (const Range<T, TRAITS>& lhs, const Range<T, TRAITS>& rhs);
598
599 /**
600 * Alias: T * RANGE => RANGE.Times(T)
601 * \pre T has operator* (T,T) -> T defined
602 */
603 template <typename T, typename TRAITS>
604 constexpr Range<T, TRAITS> operator* (const T& lhs, const Range<T, TRAITS>& rhs);
605 template <typename T, typename TRAITS>
606 constexpr Range<T, TRAITS> operator* (const Range<T, TRAITS>& lhs, const T& rhs);
607
608 /**
609 * Alias for lhs.Intersection (rhs)
610 *
611 * \par Example Usage
612 * \code
613 * using RT = Range<int>;
614 * constexpr auto eOpen = Openness::eOpen;
615 * constexpr auto eClosed = Openness::eClosed;
616 * Assert ((RT{1, 2, eOpen, eClosed} ^ RT{2, 3, eClosed, eOpen}));
617 * Assert (((RT{1, 2, eOpen, eClosed} ^ RT{2, 3, eClosed, eOpen}) == RT{2,2,eClosed,eClosed}));
618 * \endcode
619 */
620 template <typename T, typename TRAITS>
621 constexpr Range<T, TRAITS> operator^ (const Range<T, TRAITS>& lhs, const Range<T, TRAITS>& rhs);
622
623}
624
625/*
626 ********************************************************************************
627 ******************************* Implementation Details *************************
628 ********************************************************************************
629 */
630#include "Range.inl"
631
632#endif /*_Stroika_Foundation_Traversal_Range_h_ */
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A DisjointRange is NOT a range, but a collection of non-overlapping (except at the edges) Ranges....
constexpr optional< bool > DefinitelyLessThan(const Range &rhs) const
Compute a less-like notion for Range.
Definition Range.h:452
constexpr bool Contains(Common::ArgByValueType< T > r) const
Definition Range.inl:193
static constexpr Range FullRange()
Definition Range.inl:138
static constexpr Range Ball(Common::ArgByValueType< T > center, Common::ArgByValueType< UnsignedDifferenceType > radius, Openness lhsOpen=TRAITS::kLowerBoundOpenness, Openness rhsOpen=TRAITS::kUpperBoundOpenness)
returns a range centered around center, with the given radius (and optionally argument openness).
Definition Range.inl:126
constexpr Range Extend(Common::ArgByValueType< T > value) const
Definition Range.inl:380
constexpr bool empty() const
Definition Range.inl:143
constexpr Range Offset(SignedDifferenceType o) const
Definition Range.inl:416
T value_type
Range::value_type is the type of the contained elements of the range (say range of integers,...
Definition Range.h:280
constexpr T GetUpperBound() const
Definition Range.inl:405
constexpr Range Intersection(const Range &rhs) const
Definition Range.inl:329
nonvirtual Characters::String ToString(const function< Characters::String(const T &)> &elt2String=[](const T &x) -> Characters::String { return Characters::ToString(x);}) const
Definition Range.inl:428
constexpr bool Intersects(const Range< T2, TRAITS2 > &rhs) const
Definition Range.inl:259
constexpr bool operator==(const Range &rhs) const
Definition Range.inl:452
constexpr Range Times(T o) const
Definition Range.inl:422
constexpr T GetLowerBound() const
Definition Range.inl:394
constexpr Range ReplaceStart(Common::ArgByValueType< T > start) const
Construct a new Range from this, but with the given start.
Definition Range.inl:114
constexpr Range UnionBounds(const Range &rhs) const
Definition Range.inl:352
constexpr Range ReplaceEnd(Common::ArgByValueType< T > end) const
Construct a new Range from this, but with the given end.
Definition Range.inl:120
nonvirtual DisjointRange< T, Range > Union(const Range &rhs) const
Definition Range.inl:347
constexpr T GetMidpoint() const
Definition Range.inl:168
constexpr T Pin(T v) const
Definition Range.inl:174
nonvirtual constexpr Range Closure() const
Definition Range.inl:252
static constexpr Range ContainedRange(Common::ArgByValueType< T > begin, Common::ArgByValueType< T > end)
Definition Range.inl:132
constexpr UnsignedDifferenceType GetDistanceSpanned() const
Definition Range.inl:160
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
Definition ToString.inl:465
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
Definition TypeHints.h:32
This defines the default openness for a given type T, except for specializaitons. This is used by Exp...
Definition Range.h:81
static constexpr value_type GetPrevious(value_type i)
Definition Range.inl:49
static constexpr value_type GetNext(value_type i)
Definition Range.inl:35
static constexpr SignedDifferenceType Difference(Common::ArgByValueType< value_type > lhs, Common::ArgByValueType< value_type > rhs)
Definition Range.inl:17