Stroika Library 3.0d16
 
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>, typename Common::LazyType<Default_Enum, T>::type,
223 conditional_t<is_integral_v<T>, typename Common::LazyType<Default_Integral, T>::type,
224 conditional_t<is_arithmetic_v<T> or true, typename Common::LazyType<Default_Arithmetic, T>::type, void>>> {
225 };
226
227 }
228
229 template <typename T, typename RANGE_TYPE>
230 class DisjointRange;
231
232 /**
233 * A Range<> is analogous to a mathematical range. It's left and and its right sides can
234 * be optionally open or closed.
235 *
236 * Range<> is an immutable type (once constructed, will never change), except for allowing operator=.
237 *
238 * A range always has a lower and upper bound (if not specified in CTOR, its specified by the type traits) so no
239 * unbounded ranges).
240 *
241 * For a range to contain a single point, min=max, and both sides must be closed (else its a require error)
242 *
243 * This Range<> template is similar to Ruby range, and fairly DIFFERENT from the std::range<> template.
244 *
245 * This notion of range is **NOT THE SAME as std::range**, though is similar (obviously from the name).
246 *
247 * Somewhat inspired by, and at least influenced by, the definition in
248 * http://ruby-doc.org/core-2.0/Range.html
249 * However - where Ruby has one type "Range" - we have "Range" and DiscreteRange" - and some ruby Range methods/properties
250 * are expressed only in DiscreteRange<>. Also Stroika Range has openness as an optional/configurable
251 * feature of both endpoints, whereas in Ruby, the LHS is always closed and its RHS is optionally open.
252 *
253 * Note - you can do Range<float>, but cannot do DiscreteRange<float> - but can do DiscreteRange<int>.
254 *
255 * A note about an empty range. All empty ranges (of the same type) are equal to one another. It is illegal
256 * to ask for the start or end of an empty range. Empty ranges contain no points.
257 *
258 * It is illegal to call:
259 * Range<int>{1,1, Openness::eOpen, Openness::eOpen} since this would produce an empty range.
260 *
261 * Range<int>{1,1, Openness::eClosed, Openness::eClosed} != Range<int>{3,3, Openness::eClosed, Openness::eClosed}
262 * would be true, since neither is empty and they contain different points (1 vs 3).
263 *
264 * \note The default OPENNESS for Default varies by TYPE T. Integer and enums are both
265 * fully closed by default, and other arithmetic types (floats) are half open [)
266 *
267 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
268 * o Standard Stroika Comparison support (operator==, operator<=>, etc);
269 * o Depends on operator==/operator<=> being defined on T
270 *
271 * @see DiscreteRange
272 * @see DisjointRange
273 * @see DisjointDiscreteRange
274 */
275 template <typename T, typename TRAITS = RangeTraits::Default<T>>
276 class Range {
277 public:
278 /**
279 * \brief Range::value_type is the type of the contained elements of the range (say range of integers, value_type=int)
280 */
281 using value_type = T;
282
283 public:
284 /**
285 */
286 using TraitsType = TRAITS;
287
288 public:
289 /**
290 */
291 using SignedDifferenceType = typename TraitsType::SignedDifferenceType;
292
293 public:
294 /**
295 */
296 using UnsignedDifferenceType = typename TraitsType::UnsignedDifferenceType;
297
298 public:
299 /**
300 * Range{} creates an empty range (note all empty () ranges of the same type are equal to each other).
301 *
302 * optional values - if omitted - are replaced with the TRAITS::kLowerBound and TRAITS::kUpperBound values (as well as 'TRAITs' default openness).
303 * Constructors with actual numeric values (begin/end) MUST construct non-empty ranges (begin == end ==> both sides closed).
304 *
305 * \pre begin <= end (after substitution of optional values)
306 * \pre begin < end or LHS/RHS CLOSED (after substitution of optional values)
307 *
308 * \par Example Usage
309 * \code
310 * Range<double> r1{3, 5};
311 * Assert (r1.Contains (3) and not r1.Contains (3)); // because default arithmetic traits have [) half open
312 * Range<double> r2{ 3, 5, Openness::eOpen, Openness::eOpen };
313 * Assert (not r2.Contains (3));
314 * \endcode
315 */
316 constexpr explicit Range ();
317 template <typename T2, typename TRAITS2>
318 constexpr explicit Range (const Range<T2, TRAITS>& src);
319 constexpr explicit Range (Common::ArgByValueType<T> begin, Common::ArgByValueType<T> end);
320 constexpr explicit Range (const optional<T>& begin, const optional<T>& end);
321 constexpr explicit Range (Common::ArgByValueType<T> begin, Common::ArgByValueType<T> end, Openness lhsOpen, Openness rhsOpen);
322 constexpr explicit Range (const optional<T>& begin, const optional<T>& end, Openness lhsOpen, Openness rhsOpen);
323
324 public:
325 /**
326 * \brief Construct a new Range from this, but with the given start
327 * \pre start <= GetUpperBound ()
328 */
329 constexpr Range ReplaceStart (Common::ArgByValueType<T> start) const;
330
331 public:
332 /**
333 * \brief Construct a new Range from this, but with the given end
334 * \pre GetLowerBound () <= end
335 */
336 constexpr Range ReplaceEnd (Common::ArgByValueType<T> end) const;
337
338 public:
339 /**
340 * \brief returns a range centered around center, with the given radius (and optionally argument openness).
341 */
343 Openness lhsOpen = TRAITS::kLowerBoundOpenness, Openness rhsOpen = TRAITS::kUpperBoundOpenness);
344
345 public:
346 /**
347 * This returns begin>end? EMPTY else Range<T, TRAITS> (begin, end);
348 *
349 * The Range(begin/end) CTOR REQUIRES begin<=end). This does not, and just produces an empty range in that case.
350 */
352
353 public:
354 /**
355 * This returns Range{
356 * TraitsType::kLowerBound, TraitsType::kUpperBound,
357 * TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness
358 * };
359 */
360 static constexpr Range FullRange ();
361
362 public:
363 /**
364 * A Range is considered empty if it contains no points. If GetLowerBound () < GetUpperBound (),
365 * then clearly this is non-empty. If created with Range/0() - then the range this is empty.
366 *
367 * But if GetLowerBound () == GetUpperBound () - this is a trickier case. With both ends CLOSED -
368 * that means the GetLowerBound () value is contained in the range, so that is not empty.
369 *
370 * if GetLowerBound () == GetUpperBound (), and both ends open, then there are no points contained.
371 *
372 * But if GetLowerBound () == GetUpperBound (), and one one side is open, and the other closed,
373 * the one closed point endpoint is in the range, so the range is non-empty.
374 */
375 constexpr bool empty () const;
376
377 public:
378 /**
379 * \brief equivalent to not this->empty ();
380 */
381 constexpr explicit operator bool () const;
382
383 public:
384 /**
385 * GetUpperBound ()-GetLowerBound (), or distance from GetLowerBound () to end of the range.
386 * If this is empty (), then GetDistanceSpanned () will be zero but the GetDistanceSpanned CAN be zero without the
387 * range being empty (if both ends are closed).
388 *
389 * \note this just uses TraitsType::Difference ()
390 *
391 * \note For discrete Ranges, this does NOT correspond to the number of points (this is one less)
392 */
393 constexpr UnsignedDifferenceType GetDistanceSpanned () const;
394
395 public:
396 /**
397 * \pre not empty ()
398 */
399 constexpr T GetMidpoint () const;
400
401 public:
402 /**
403 * Compare v with the upper and lower bounds of this range, and return a value as close as
404 * possible to v but in range.
405 *
406 * If 'v' is not in range, and this Range is open, GetNext or GetPrevious maybe used to find a value
407 * in range.
408 *
409 * \pre not empty ()
410 *
411 * @see std::clamp
412 */
413 constexpr T Pin (T v) const;
414
415 public:
416 /**
417 * This corresponds to the mathematical set containment. When comparing with the edges
418 * of the range, we check <= if the edge is closed, and < if the edge is open.
419 */
420 constexpr bool Contains (Common::ArgByValueType<T> r) const;
421 constexpr bool Contains (const Range& containee) const;
422
423 public:
424 /**
425 * Returns an identical Range to this, but including its end points.
426 *
427 * \pre not empty ();
428 */
429 nonvirtual constexpr Range Closure () const;
430
431 public:
432 /**
433 * \note All empty ranges (of the same type) are equal to each other.
434 */
435 constexpr bool operator== (const Range& rhs) const;
436
437 public:
438 /**
439 */
440 constexpr partial_ordering operator<=> (const Range& rhs) const;
441
442 public:
443 /**
444 * \brief Compute a less-like notion for Range.
445 *
446 * There is no clear way to provide an ordering of two ranges (of the same type). The ordering of their
447 * left sides, may not agree with the ordering of their right sides, or their midpoints.
448 *
449 * But - OFTEN - they CAN be ordered! And that's often a useful concept. So capture that case at least.
450 * Just return nullopt if not comparable. Then the caller can decide how to break the 'tie' - with midpoint compare, or
451 * left or right edge compares...
452 */
453 [[deprecated ("USE operator<==> - check <=> produces less (vs unordered) ")]] constexpr optional<bool> DefinitelyLessThan (const Range& rhs) const
454 {
455 return (*this <=> rhs) == partial_ordering::less;
456 }
457
458 public:
459 /**
460 * Returns true iff there are any points shared in common between this range and the rhs range.
461 *
462 * \par Example Usage
463 * \code
464 * using RT = Range<int>;
465 * constexpr auto eOpen = Openness::eOpen;
466 * constexpr auto eClosed = Openness::eClosed;
467 * Assert ((RT{1, 2}.Intersects (RT{1, 2})));
468 * Assert ((not RT{1, 2, eOpen, eOpen}.Intersects (RT{2, 3, eOpen, eOpen})));
469 * Assert ((not RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eOpen, eOpen})));
470 * Assert ((RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eClosed, eOpen})));
471 * \endcode
472 *
473 * \see operator^
474 */
475 template <typename T2, typename TRAITS2>
476 constexpr bool Intersects (const Range<T2, TRAITS2>& rhs) const;
477
478 public:
479 /**
480 * Compute the overlap/intersection between two ranges. The resulting range defines exactly the points in both places (so respects openness).
481 *
482 * @see operator^ - an operator alias for this function
483 */
484 constexpr Range Intersection (const Range& rhs) const;
485
486 public:
487 /**
488 * if two regions are disjoint, this can encompass a larger region than the actual union would
489 */
490 nonvirtual DisjointRange<T, Range> Union (const Range& rhs) const;
491
492 public:
493 /**
494 * if two regions are disjoint, this can encompass a larger region than the actual union would
495 *
496 * \note See also Extend ();
497 * \note See also Union ();
498 */
499 constexpr Range UnionBounds (const Range& rhs) const;
500
501 public:
502 /**
503 * Construct a new range from this range, but including the given point
504 * Note that can produce a range with different openness from the starting range (as the points added close the endpoints).
505 *
506 * \note See also UnionBounds ();
507 */
508 constexpr Range Extend (Common::ArgByValueType<T> value) const;
509
510 public:
511 /**
512 * \pre not empty (); // special case - no upper/lower bound
513 */
514 constexpr T GetLowerBound () const;
515
516 public:
517 /**
518 */
519 constexpr Openness GetLowerBoundOpenness () const;
520
521 public:
522 /**
523 * \pre not empty (); // special case - no upper/lower bound
524 */
525 constexpr T GetUpperBound () const;
526
527 public:
528 /**
529 */
530 constexpr Openness GetUpperBoundOpenness () const;
531
532 public:
533 /**
534 * \pre not empty
535 * \pre the Range produced by applying the given offset to *this remains valid with respect to the constraints on this Range.
536 */
537 constexpr Range Offset (SignedDifferenceType o) const;
538
539 public:
540 /**
541 * \pre not empty
542 * \pre the Range produced by applying the given factor to the upper and lower bounds.
543 * \pre T has operator* (T,T) -> T defined
544 */
545 constexpr Range Times (T o) const;
546
547 public:
548 /**
549 * Print a displayable rendition of the given range, using the argument function to format
550 * the basic value_type.
551 *
552 * \par Example Usage
553 * \code
554 * Assert (Range<int>{3, 4}.ToString () == "[3 ... 4)");
555 * Assert (Range<int>{3, 4}.ToString ([] (int n) { return "{}"_f (n); }) == "[3 ... 4)");
556 * \endcode
557 *
558 * if the 'UpperBound' == kUpperBound, its not shown
559 *
560 * \par Example Usage
561 * \code
562 * Assert (Range<int>{3, nullopt}.ToString () == "[3 ... ]");
563 * \endcode
564 *
565 * Similarly for (only) LowerBound == kLowerBound
566 *
567 * \par Example Usage
568 * \code
569 * Assert (Range<int>{nullopt, 4}.ToString () == "[ ... 4]");
570 * \endcode
571 * @see Characters::ToString ();
572 */
573 nonvirtual Characters::String ToString (const function<Characters::String (const T&)>& elt2String = [] (const T& x) -> Characters::String {
574 return Characters::ToString (x);
575 }) const;
576
577 private:
578 T fBegin_;
579 T fEnd_;
580 Openness fBeginOpenness_;
581 Openness fEndOpenness_;
582 };
583
584 /**
585 */
586 template <typename RANGE_TYPE>
587 concept IRange = derived_from<RANGE_TYPE, Range<typename RANGE_TYPE::value_type, typename RANGE_TYPE::TraitsType>>;
588
589 /**
590 * Alias: T + RANGE => RANGE.Offset(T)
591 * Alias: RANGE + RANGE => RANGE.Union (RANGE)
592 */
593 template <typename T, typename TRAITS>
594 constexpr Range<T, TRAITS> operator+ (const T& lhs, const Range<T, TRAITS>& rhs);
595 template <typename T, typename TRAITS>
596 constexpr Range<T, TRAITS> operator+ (const Range<T, TRAITS>& lhs, const T& rhs);
597 template <typename T, typename TRAITS>
598 DisjointRange<T, Range<T, TRAITS>> operator+ (const Range<T, TRAITS>& lhs, const Range<T, TRAITS>& rhs);
599
600 /**
601 * Alias: T * RANGE => RANGE.Times(T)
602 * \pre T has operator* (T,T) -> T defined
603 */
604 template <typename T, typename TRAITS>
605 constexpr Range<T, TRAITS> operator* (const T& lhs, const Range<T, TRAITS>& rhs);
606 template <typename T, typename TRAITS>
607 constexpr Range<T, TRAITS> operator* (const Range<T, TRAITS>& lhs, const T& rhs);
608
609 /**
610 * Alias for lhs.Intersection (rhs)
611 *
612 * \par Example Usage
613 * \code
614 * using RT = Range<int>;
615 * constexpr auto eOpen = Openness::eOpen;
616 * constexpr auto eClosed = Openness::eClosed;
617 * Assert ((RT{1, 2, eOpen, eClosed} ^ RT{2, 3, eClosed, eOpen}));
618 * Assert (((RT{1, 2, eOpen, eClosed} ^ RT{2, 3, eClosed, eOpen}) == RT{2,2,eClosed,eClosed}));
619 * \endcode
620 */
621 template <typename T, typename TRAITS>
622 constexpr Range<T, TRAITS> operator^ (const Range<T, TRAITS>& lhs, const Range<T, TRAITS>& rhs);
623
624}
625
626/*
627 ********************************************************************************
628 ******************************* Implementation Details *************************
629 ********************************************************************************
630 */
631#include "Range.inl"
632
633#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:453
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:281
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