Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
Iterable.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_Iterable_h_
5#define _Stroika_Foundation_Traversal_Iterable_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <compare>
10#include <concepts>
11#include <functional>
12#include <ranges>
13#include <span>
14#include <vector>
15
16#include "Stroika/Foundation/Common/Common.h"
18#include "Stroika/Foundation/Common/Concepts.h"
22#include "Stroika/Foundation/Execution/Common.h"
26
27/**
28 * \file
29 *
30 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
31 *
32 * TODO:
33 * @todo For methods similar to Iterable<T>::Where() (did for where),
34 * consider a TEMPLATED PARAMETER for the resulting Container type, so you can create a "Set" or whatever by doing
35 * Where... But tricky to uniformly add to different container types. Maybe only ones you can say add, or the adder is
36 * a template paraM?
37 * Eg. Distinct, Take, Skip (maybe those sense logically to be transform operations - so maybe OK now doing others but review
38 * each to see where it makes sense).
39 *
40 * @todo SUBCLASSES of Iterable<> need to overload/replace several of these functions taking
41 * into account (by default) their comparers... Eg. Set<> should overload Distinct to do nothing by
42 * default.
43 *
44 * @todo max should take lambda that folds in the select,
45 * and Distinct and take lambda
46 *
47 * @todo Document (which -not all) Linq-like functions only pull as needed from the
48 * original source, and which force a pull (like where doesn't but max does).
49 *
50 * @todo Consider having Linq-like functions do DELAYED EVALUATION, so the computation only
51 * happens when you iterate. Maybe to some degree this already happens, but could do
52 * more (as MSFT does).
53 *
54 * @todo Ordering of parameters to SetEquals() etc templates? Type deduction versus
55 * default parameter?
56 *
57 * @todo REDO DOCS FOR ITERABLE - SO CLEAR ITS ALSO THE BASIS OF "GENERATORS". IT COULD BE RENAMED
58 * GENERATOR (though don't)
59 */
60
62 class String;
63 extern const function<String (String, String, bool)> kDefaultStringCombiner;
64 template <typename T>
65 String UnoverloadedToString (const T& t);
66}
67
68namespace Stroika::Foundation::Traversal {
69
71 using Common::IEqualsComparer;
72 using Common::IThreeWayComparer;
73
74 /**
75 * IIterable concept: std::ranges::range and iterated over values satisfy argument predicate (if given)
76 *
77 * Checks if argument is ranges::range and if the value of items iterated over ITEM_PREDICATE.
78 *
79 * https://stackoverflow.com/questions/76532448/combining-concepts-in-c-via-parameter
80 */
81 template <typename ITERABLE, template <typename> typename ITEM_PREDICATE = Common::True>
82 concept IIterable = ranges::range<ITERABLE> and ITEM_PREDICATE<ranges::range_value_t<ITERABLE>>::value;
83
84 /**
85 * IIterableOfTo concept: IIterable with the constraint that the items produced by iteration are 'ConvertibleTo' the argument OF_T type
86 *
87 * Checks if argument is ranges::range and if the value of items iterated over is convertible to OF_T.
88 *
89 * \par Example Usage
90 * \code
91 * template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
92 * void Add (ITERABLE_OF_ADDABLE&& addAll);
93 * \endcode
94 */
95 template <typename ITERABLE, typename OF_T>
97 static_assert (IIterableOfTo<vector<int>, int>);
98 static_assert (IIterableOfTo<vector<long int>, int>);
99 static_assert (IIterableOfTo<vector<int>, long int>);
100 static_assert (not IIterableOfTo<vector<string>, int>);
101
102 /**
103 * IIterableOfFrom concept: IIterable with the constraint that the items produced by iteration are 'ConvertibleFrom' the argument OF_T type
104 *
105 * Checks if argument is ranges::range and if the value of items iterated over is convertible to OF_T.
106 */
107 template <typename ITERABLE, typename OF_T>
109 static_assert (IIterableOfFrom<vector<int>, int>);
110 static_assert (IIterableOfFrom<vector<long int>, int>);
111 static_assert (IIterableOfFrom<vector<int>, long int>);
112 static_assert (not IIterableOfFrom<vector<string>, int>);
113
114#if qCompilerAndStdLib_lambdas_in_unevaluatedContext_warning_Buggy
115 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wsubobject-linkage\"")
116#endif
117
118 /**
119 * \brief Iterable<T> is a base class for containers which easily produce an Iterator<T>
120 * to traverse them.
121 *
122 * The Stroika iterables can be used either directly (similar to std::range), or in the STL begin/end style -
123 * and this class supports both styles of usage.
124 *
125 * Iterable<T> also supports read-only applicative operations on the contained data.
126 *
127 * Iterable<T> is much like idea of 'abstract readonly container', but which only supports an
128 * exceedingly simplistic pattern of access.
129 *
130 * \note Satisfies Concepts:
131 * o copyable<Iterable<T>> // not not default-unitarizable, and not equals_comparable
132 *
133 * *Important Design Note* (lifetime of iterators):
134 * The Lifetime of Iterator<T> objects created by an Iterable<T> instance must always be less
135 * than the creating Iterable's lifetime.
136 *
137 * This may not be enforced by implementations (but generally will be in debug builds). But
138 * it is a rule!
139 *
140 * The reason for this is that the underlying memory referenced by the iterator may be going away.
141 * We could avoid this by adding a shared_ptr<> reference count into each iterator, but that
142 * would make iterator objects significantly more expensive, and with little apparent value added.
143 * Similarly for weak_ptr<> references.
144 *
145 * *Important Design Note* (construct with rep, no setrep):
146 * We have no:
147 * nonvirtual void _SetRep (IterableRepSharedPtr rep);
148 *
149 * because allowing a _SetRep() method would complicate the efforts of subclasses of Iterable<T>
150 * to assure that the underlying type is of the appropriate subtype.
151 *
152 * For example - see Bag_Array<T>::GetRep_().
153 *
154 * Note - instead - you can 'assign' (operator=) to replace the value (and dynamic type) of
155 * an Iterable<> (or subclass) instance.
156 *
157 * *Important Design Note* (copy on write/COW):
158 * Iterable uses 'SharedByValue', so that subclasses of Iterable (especially containers) CAN implement
159 * Copy-On-Write (COW). However, not ALL Iterables implement COW. In fact, not all Iterables are mutable!
160 *
161 * Iterable's data can come from arbitrary, programmatic sources (like a sequence of uncomputed random numbers).
162 * If you wish to capture something like an Iterable for later use, but don't want its value to change once you've captured it,
163 * consider using Collection<T> or Sequence<> which is almost the same, but will make a copy of the data, and not allow it to
164 * change without preserve COW semantics.
165 *
166 * *Design Note*:
167 * Why does Iterable<T> contain a size () method?
168 *
169 * o It’s always well defined what size() means (what you would get if you called
170 * MakeIterable() and iterated a bunch of times til the end).
171 *
172 * o Its almost always (and trivial) to perform that computation more efficiently than the
173 * iterate over each element approach.
174 *
175 * The gist of these two consideration means that if you need to find the length of
176 * an Iterable<T>, if it was defined as a method, you can access the trivial implementation,
177 * and if it was not defined, you would be forced into the costly implementation.
178 *
179 * Adding size () adds no conceptual cost – because its already so well and clearly defined
180 * in terms of its basic operation (iteration). And it provides value (maybe just modest value).
181 *
182 * *Design Note*:
183 * Order of Iteration.
184 *
185 * Iterables<T> provide no promises about the order of iteration. Specific subclasses (like SortedSet<>)
186 * often will make specific guarantees about order of iteration.
187 *
188 * We do NOT even promise you will see the same items, or seem them in the same order as you iterate
189 * (so for example, you can have a "RandomSequence<>" subclass from Iterable<> and return a different
190 * sequence of numbers each time you make an iterate and run.
191 *
192 * *Design Note*:
193 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
194 * Chose NOT to include an equal_to<Iterable<T>> partial specialization here, but instead duplicatively in
195 * each subclass, so that it could more easily be implemented efficiently (not a biggie), but more
196 * importantly because it doesn't appear to me to make sense so say that a Stack<T> == Set<T>, even if
197 * their values were the same. In other words, the meaning of 'equals' varies between different kinds of
198 * iterables (over the same type).
199 *
200 * We DO have methods SetEquals/MultiSetEquals/SequentialEquals (see below), as well as SequentialThreeWayComparer<> etc.
201 *
202 * \em Design Note
203 * Methods like Min/Max/Median/Sum make little sense on empty Iterables. There were several choices
204 * available to deal with this:
205 * > Assertion
206 * > throw range_error()
207 * > return a sensible default value (e.g. 0) for empty lists
208 * > overloads to let callers select the desired behavior
209 *
210 * Because I wanted these methods to be useful in scenarios like with database queries (inspired by Linq/ORMs)
211 * assertions seemed a poor choice.
212 *
213 * throw range_error makes sense, but then requires lots of checking when used for throws, and that makes use needlessly complex.
214 *
215 * So we eventually decided to use the return optional and have a variant named XXXValue () that returns the plain T with a default - since
216 * we use that pattern in so many places.
217 *
218 * *Design Note* - Microsoft Linq:
219 * This API implements some of the Microsoft Linq API.
220 * https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods(v=vs.100).aspx
221 *
222 * For example, we implement:
223 * o Map **most important**
224 * o Reduce **important - aka accumulate**
225 * o Where
226 * o Take
227 * o Skip
228 * o OrderBy
229 * o First/Last/FirstValue/LastValue (though semantics and later names differ somewhat from .net FirstOrDefault)
230 *
231 * We choose explicitly not to implement
232 * o ToList/ToArray, no need because we have As<>, plus no List/Array classes (exactly).
233 *
234 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
235 *
236 */
237 template <typename T>
238 class Iterable {
239 // requirements about properties of 'T' which logically should have been template type constraints, but wasn't able to get
240 // that working
241 public:
242 static_assert (copy_constructible<Iterator<T>>, "Must be able to create Iterator<T> to use Iterable<T>");
243#if !qCompilerAndStdLib_constructible_Buggy
244 static_assert (copyable<T>); // cannot use as type constraint on T cuz fails with String - cuz??? not sure why - something about being evaluated when incomplete type...
245#endif
246
247 public:
248 /**
249 * \brief value_type is an alias for the type iterated over - like vector<T>::value_type
250 */
251 using value_type = T;
252
253 public:
254 /**
255 * For Stroika containers, all iterators are really const_iterators, but this allows for better STL interoperability.
256 */
258
259 public:
260 /**
261 * For better STL interoperability.
262 */
264
265 protected:
266 class _IRep;
267
268 public:
269 /**
270 * \brief Iterable are safely copyable (by value). Since Iterable uses COW, this just copies the underlying pointer and increments the reference count.
271 */
272 Iterable (const Iterable&) noexcept = default;
273
274 public:
275 /**
276 * \brief Iterable are safely moveable.
277 */
278 Iterable (Iterable&&) noexcept = default;
279
280 public:
281 /**
282 * Make a copy of the given argument, and treat it as an iterable.
283 *
284 * \par Example Usage
285 * \code
286 * Iterable<int> aa6{3, 4, 6};
287 * \endcode
288 *
289 * \note Don't apply this constructor to non-containers (non-iterables),
290 * and don't allow it to apply to SUBCLASSES of Iterable (since then we want to select the Iterable (const Iterable& from) constructor)
291 */
295#if !qCompilerAndStdLib_constructible_Buggy
297#endif
298 )
300 : _fRep{mk_ (forward<CONTAINER_OF_T> (from))._fRep} {}
301#endif
302 ;
303
304 public:
305 /**
306 * \note Use of initializer_list<T> (@see https://github.com/SophistSolutions/Stroika/issues/873 (STK-739))
307 * Because of quirks of C++ overload resolution (https://en.cppreference.com/w/cpp/language/list_initialization)
308 * use of mem-initializers with Iterable<T> constructor calls have the unintuitive behavior of
309 * invoking the initializer_list<T> constructor preferentially (see docs above and 'Otherwise, the constructors of T are considered, in two phases'
310 */
312
313 protected:
314 /**
315 * \brief Iterable's are typically constructed as concrete subtype objects,
316 * whose CTOR passed in a shared copyable rep.
317 *
318 * \note - the repPtr in construction can be, so that we don't
319 * need to increment its reference count as we pass it though the call chain to where it will be finally
320 * stored.
321 */
322 explicit Iterable (const shared_ptr<_IRep>& rep) noexcept;
323 explicit Iterable (shared_ptr<_IRep>&& rep) noexcept;
324
325 public:
326 ~Iterable () = default;
327
328 public:
329 /**
330 */
331 nonvirtual Iterable& operator= (Iterable&& rhs) noexcept = default;
332 nonvirtual Iterable& operator= (const Iterable& rhs) noexcept = default;
333
334 public:
335 /**
336 * Often handy short-hand (punning) for a container to see if zero elts, then if on it returns false.
337 */
338 nonvirtual explicit operator bool () const;
339
340 public:
341 /**
342 * \brief Create an iterator object which can be used to traverse the 'Iterable'.
343 *
344 * Create an iterator object which can be used to traverse the 'Iterable' - this object -
345 * and visit each element.
346 *
347 * \note LIFETIME NOTE:
348 * Iterators created this way, become invalidated (generally detected in debug builds), and cannot be used
349 * after the underlying Iterable is modified.
350 */
351 nonvirtual Iterator<T> MakeIterator () const;
352
353 public:
354 /**
355 * \brief Returns the number of items contained.
356 *
357 * size () returns the number of elements in this 'Iterable' object. Its defined to be
358 * the same number of elements you would visit if you created an iterator (MakeIterator())
359 * and visited all items. In practice, as the actual number might vary as the underlying
360 * iterable could change while being iterated over.
361 *
362 * For example, a filesystem directory iterable could return a different length each time it was
363 * called, as files are added and removed from the filesystem.
364 *
365 * Also note that size () can return a ridiculous number - like numeric_limits<size_t>::max () -
366 * for logically infinite sequences... like a sequence of random numbers.
367 *
368 * @aliases GetLength () - in fact in Stroika before 2.1b14, this was called GetLength ()
369 *
370 * \note Design Note: noexcept
371 * We chose to allow the empty () method to allow exceptions, since an Iterable<T>
372 * is general enough (say externally network data sourced) - it could be temporarily or otherwise unavailable.
373 *
374 * \em Performance:
375 * The performance of size() may vary wildly. It could be anywhere from O(1) to O(N)
376 * depending on the underlying type of Iterable<T>.
377 *
378 * \note Design Note: there is deliberately NO PeekSize () -> optional<size_t> ("tell me your
379 * size only if it is cheap"). Considered at length and NOT built; recorded here so it is
380 * not re-derived, since this is where anyone wanting it would look.
381 *
382 * Every Stroika CONTAINER does have O(1) size () - both linked lists cache their length,
383 * so every DataStructures class does (see Containers/DataStructures/ReadMe.md). The
384 * guarantee stops at Iterable<T> because an Iterable need not be a container: it may be a
385 * generator, or a lazy pipeline - Where () returns a lazy Iterable<T> - whose count cannot
386 * be known without running a predicate over every element, and running it may not even be
387 * repeatable (socket, file). That is not an implementation gap; caching cannot cache what
388 * was never computed.
389 *
390 * Two tempting shapes were rejected:
391 * o returning numeric_limits<size_t>::max () for "unknown" - it makes an unknown look
392 * like a number, and callers do arithmetic on size (): Median () computes size ()/2,
393 * reserve (size ()) throws, size () - 1 wraps, 'i < size ()' becomes an infinite
394 * loop. It fails silently and late, and collapses three distinct states
395 * (known-and-cheap / knowable-but-expensive / unbounded) into one value.
396 * o overloading this virtual (size (SizeQuery)) to avoid adding a second one - there
397 * are 41 in-tree overrides of 'size () const override' plus out-of-tree backends,
398 * all of which would have to change, to save one vtable slot. Default arguments on
399 * virtuals also bind to the STATIC type, which is its own trap.
400 *
401 * If it is ever actually wanted, the shape to build is NOT a virtual: "is my size () cheap"
402 * is a per-TYPE constant needing no dynamic dispatch, so put a protected bool on
403 * Iterable<T>::_IRep (defaulting to false = "I promise nothing"), set it in backends that
404 * can guarantee it, and make PeekSize () a non-virtual on Iterable<T> that reads it. That
405 * costs zero vtable slots - the objection to a virtual being that its body cannot be
406 * stripped by the linker, and _IRep is a template so it multiplies by every T - and touches
407 * none of the 41 overriders. Its weakness is an unchecked promise: a backend could lie.
408 *
409 * What would justify building it: a real heuristic inside the no-policy overloads, where
410 * the "@todo measure the crossover and auto-choose the policy here - eSeq is a placeholder,
411 * not a decision" notes sit in Iterable.inl / Sequence.inl. Choosing a policy by size needs
412 * a cheap size, and nullopt has an obvious right answer there (use eSeq). Until something
413 * concrete needs that, do not add it.
414 *
415 * \note Design Note: do NOT use this to pre-size a copy of an arbitrary Iterable<T>, and do not
416 * pre-size via MakeRandomAccessIterator () unconditionally. Sequence_LinkedList and
417 * Sequence_DoublyLinkedList return _MakeRandomAccessIterator_ViaGetAt () for random access
418 * (the doubly-linked one is natively only BIDIRECTIONAL), so a vector range CTOR over one
419 * goes O(n^2). Separately, an explicit reserve () measured 1.33x-1.55x SLOWER than simply
420 * letting the range CTOR size the target itself, so it was not adopted. Do not reintroduce
421 * either without new evidence; a cheap PeekSize () above is what would change the picture.
422 */
423 nonvirtual size_t size () const;
424
425 public:
426 /**
427 * \brief Returns true iff size() == 0
428 *
429 * @aliases IsEmpty () - called IsEmpty () in Stroika 2.1b13 and prior
430 *
431 * \note Design Note: noexcept
432 * We chose to allow the empty () method to allow exceptions, since an Iterable<T>
433 * is general enough (say externally network data sourced) - it could be temporarily or otherwise unavailable.
434 *
435 * \note Runtime performance/complexity:
436 * The performance of empty() may vary wildly (@see size) but will nearly always be constant complexity.
437 */
438 nonvirtual bool empty () const;
439
440 public:
441 /**
442 * Apply the (template argument) EQUALS_COMPARER to each element in the Iterable<T> and
443 * return true iff found. This invokes no virtual methods dependent (except MakeIterable or some such)
444 * and so gains no performance benefits from the organization of the underlying Iterable<T>. This
445 * is just a short hand for the direct iteration one would trivially code by hand. Still - its
446 * easier to call Contains() that to code that loop!
447 *
448 * And note - subclasses (like Containers::Set<T>) will hide this implementation with a more
449 * efficient one (that does indirect to the backend).
450 *
451 * \em Performance:
452 * This algorithm is O(N).
453 *
454 */
455 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
456 nonvirtual bool Contains (ArgByValueType<T> element, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
457
458 public:
459 /**
460 * SetEquals () - very inefficiently - but with constant small memory overhead - returns true if
461 * each element in the each iterable is contained in the other. The lengths may be different
462 * and even though the two Iterables<> are SetEquals().
463 *
464 * \em Performance:
465 * This algorithm is O(N) * O(M) where N and M are the length of the two respective iterables.
466 *
467 * \note \todo - consider alternative implementation where we accumulate into std::set<>.
468 * Assume without loss of generality that N is the smaller side (can be determined in O(M)).
469 * Accumulate into set would take N*log (N).
470 * Then we would iterate over M (O(M)), and each time check log(N)). So time would be sum of
471 * N*log (N) + M*(log(N)) or (N + M)*log(N).
472 * That's a little better (but at the cost of more RAM usage).
473 * NOTE ALSO - that 'trick' assumes T has a valid less<T>, which it may not!
474 *
475 */
476 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
477 static bool SetEquals (const LHS_CONTAINER_TYPE& lhs, const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{});
478 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
479 nonvirtual bool SetEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
480
481 public:
482 /**
483 * MultiSetEquals () - very inefficiently - but with constant small memory overhead - returns true if
484 * each element in the each iterable is contained in the other the same number of times.
485 *
486 * \em Performance:
487 * This algorithm is O(N^^3)
488 */
489 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
490 static bool MultiSetEquals (const LHS_CONTAINER_TYPE& lhs, const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{});
491 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
492 nonvirtual bool MultiSetEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
493
494 public:
495 /**
496 * SequentialEquals () - measures if iteration over the two containers produces identical sequences
497 * of elements (identical by compare with EQUALS_COMPARER). It does not call 'size', but just iterates.
498 *
499 * \note - RHS_CONTAINER_TYPE can be any iterable, including an STL container like vector or initializer_list
500 *
501 * \em Performance:
502 * This algorithm is O(N).
503 *
504 * Where BOTH arguments are contiguous runs of T - an Iterable<T> whose backend offers
505 * _IRep::PeekContiguousStorage (), or any other contiguous_range of T such as vector<T> or
506 * initializer_list<T> - they are compared as spans rather than by advancing two Iterator<T>s,
507 * and where EQUALS_COMPARER is the default the comparison degenerates to a memcmp.
508 */
509 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
511 EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{});
512 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
513 nonvirtual bool SequentialEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
514 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER>
515 [[deprecated ("Since Stroika v3.0d24 - useIterableSize is ignored; use the overload without it")]] static bool
517 template <ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER>
518 [[deprecated ("Since Stroika v3.0d24 - useIterableSize is ignored; use the overload without it")]] nonvirtual bool
519 SequentialEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer, bool useIterableSize) const;
520
521 public:
522 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) T_EQUALS_COMPARER = equal_to<T>>
523 struct SequentialEqualsComparer;
524
525 public:
526 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IThreeWayComparer<T>) T_THREEWAY_COMPARER = compare_three_way>
527 struct SequentialThreeWayComparer;
528
529 public:
530 /**
531 * \brief Support for ranged for, and STL syntax in general
532 *
533 * begin ()/end() are similar to MakeIterator(), except that they allow for iterators to be
534 * used in an STL-style, which is critical for using C++ ranged iteration.
535 *
536 * \par Example Usage
537 * \code
538 * for (Iterator<T> i = c.begin (); i != c.end (); ++i) {
539 * if (*i = T{}) {
540 * break;
541 * }
542 * }
543 * \endcode
544 *
545 * OR
546 * \code
547 * for (const T& i : c) {
548 * if (*i = T{}) {
549 * break;
550 * }
551 * }
552 * \endcode
553 *
554 */
555 nonvirtual Iterator<T> begin () const;
556
557 public:
558 /**
559 * \brief Support for ranged for, and STL syntax in general
560 *
561 * \note in INCOMPATIBLE change in Stroika v3.0d1 - from v2.1 - making this instance method instead of static method (needed for 'std::ranges' concept compatibility).
562 * \note in Stroika v3.0d10 - changed return type to default_sentinel_t (from Iterator<T>).
563 */
564 static constexpr default_sentinel_t end () noexcept;
565
566 public:
567 /**
568 * \brief Run the argument function (or lambda) on each element of the container.
569 *
570 * Take the given function argument, and call it for each element of the container. This
571 * is equivalent to:
572 *
573 * for (Iterator<T> i = begin (); i != end (); ++i) {
574 * (doToElement) (*i);
575 * }
576 *
577 * However, Apply () MAY perform the entire iteration more quickly (depending on the
578 * kind of the container).
579 *
580 * Apply () also MAY be much faster than normal iteration (some simple tests
581 * - around 2015-02-15 - suggest Apply () is perhaps 10x faster than using an iterator).
582 *
583 * \par Example Usage
584 * \code
585 * unsigned int cnt { 0 };
586 * s.Apply ([&cnt] (int i) {
587 * cnt += i;
588 * });
589 * DbgTrace ("cnt={}"_f, cnt);
590 * \endcode
591 *
592 * \note on 'seq' parameter, if you pass anything but eSeq, be sure to check that the function
593 * argument is threadsafe.
594 *
595 * \note The overload taking NO SequencePolicy leaves the choice to the implementation. Today it
596 * runs sequentially, but that is NOT a promise: it may become eSeq, ePar, eParUnseq or
597 * eUnseq (SIMD), chosen by heuristic (element count, backend, ...).
598 *
599 * So 'doToElement' must be safe under ANY of them:
600 *
601 * o No unsynchronized side effects on shared state - it may run on several threads at once.
602 * o No dependence on the ORDER elements are visited in, nor on which thread visits them.
603 * o It must NOT throw. Every policy-taking std algorithm calls std::terminate () when an
604 * element access function exits via an exception, rather than propagating it - see
605 * [algorithms.parallel.exceptions]. The eSeq path uses the plain (policy-free) algorithm,
606 * where the exception propagates normally, so this differs by policy.
607 * o Under the unsequenced policies (eUnseq / eParUnseq) it must additionally avoid
608 * vectorization-unsafe operations - allocation, and taking a lock. Calls may interleave
609 * WITHIN a single thread there, so a mutex can deadlock against itself.
610 *
611 * If 'doToElement' cannot meet all of that, pass Execution::SequencePolicy::eSeq explicitly.
612 * That is not a workaround - it is how you state the sequential semantics are load-bearing,
613 * and it keeps working when the unspecified overload starts choosing for itself.
614 *
615 * \note Aliases:
616 * o Apply could have logically been called ForEach, and is nearly identical to
617 * std::for_each (), except for not taking iterators as arguments, and not having
618 * any return value.
619 *
620 * \note Why Apply takes std::function argument instead of templated FUNCTION parameter?
621 * Because Stroika iterables use a 'virtual' APPLY, you cannot pass arbitrary templated
622 * function calls passed that boundary. That choice ALLOWS traversal to be implemented
623 * quickly, and without and subsequent (virtual) calls on the container side, but one
624 * - CALL per iteration to the function itself.
625 *
626 * \note \em Thread-Safety The argument function (lambda) may
627 * directly (or indirectly) access the Iterable<> being iterated over.
628 */
629 nonvirtual void Apply (const function<void (ArgByValueType<T> item)>& doToElement) const;
630 nonvirtual void Apply (const function<void (ArgByValueType<T> item)>& doToElement, Execution::SequencePolicy seq) const;
631
632 public:
633 /**
634 * \brief Run the argument bool-returning function (or lambda) on the elements of the container,
635 * and return an iterator pointing at AN element for which it returned true - not
636 * necessarily the first (see the note below; use First () if you need the first).
637 *
638 * Take the given function argument, and call it for the elements of the container. A simple
639 * implementation - and what the default one does - is:
640 *
641 * for (Iterator<T> i = begin (); i != end (); ++i) {
642 * if (that (*i)) {
643 * return it;
644 * }
645 * }
646 * return end();
647 *
648 * ...but that is an EXAMPLE, not the specification: a backend is free to consult an index, or to
649 * search several elements at once, so it may return a different match than the loop above would,
650 * and it may call 'that' on elements the loop would have stopped short of.
651 *
652 * This function returns an iterator pointing to an element for which 'that' returned true (for
653 * example the element you were searching for?). It returns the special iterator end() to indicate
654 * no call to 'that' returned true.
655 *
656 * Also, note that this function does NOT change any elements of the Iterable.
657 *
658 * \note Find () returns SOME matching element - NOT necessarily the first in iteration order.
659 * If you need THE first, call Iterable<>::First (); that is what it is for.
660 *
661 * This is deliberately NOT tied to the SequencePolicy. 'Which match' is a statement about
662 * the freedom the algorithm has, not about how it happens to be executing, and keeping the
663 * two separate leaves a backend free to answer from a hash bucket, a SIMD scan, or a
664 * parallel one without the answer's meaning changing with the policy argument. It also
665 * keeps 'seq' meaning what it means in std::<execution>, where the policy never changes
666 * WHICH element std::find_if () returns.
667 *
668 * Note also that for an UNORDERED Iterable (Set<T>, Mapping<>, Collection<T>) 'first' is a
669 * property of the current iteration order rather than of the data, so the guarantee would
670 * be close to vacuous there in any case.
671 *
672 * The overloads taking 'startAt' below are the exception - 'search onward from here' is
673 * inherently ordered, and they keep that meaning.
674 *
675 * Note that this used to be called 'ContainsWith' - because it can act the same way (due to
676 * operator bool () method of Iterator<T>).
677 *
678 * \note This is much like First(), except that it optionally takes a different starting point, it
679 * returns an Iterator<T> instead of an optional<T>, and - see above - it does NOT promise the
680 * first match. First () - often more handy.
681 *
682 * \note though semantically similar to iterating, it maybe faster, due to delegating 'search' to backend container
683 * implementation (though then call to lambda/checker maybe indirected countering this performance benefit).
684 *
685 * @see Apply
686 *
687 * \note \em Thread-Safety The argument function (lambda) may
688 * directly (or indirectly) access the Iterable<> being iterated over.
689 *
690 * \par Example Usage
691 * \code
692 * bool IsAllWhitespace (String s) const
693 * {
694 * return not s.Find ([] (Character c) -> bool { return not c.IsWhitespace (); });
695 * }
696 * \endcode
697 *
698 * \see See Also First (f) - if you just want the first one...
699 *
700 * \note - because the lifetime of the iterable must exceed that of the iterator, its generally unsafe to use Find()
701 * on a temporary (except with the trick if (auto i = x().Find(...)) { ok to access i here cuz x() temporary
702 * not destroyed yet).
703 *
704 * \note despite the name EQUALS_COMPARER, we allow EQUALS_COMPARER to just be IPotentiallyComparer<> and don't require
705 * EqualsComparer, just to simplify use, and because we cannot anticipate any real ambiguity or confusion resulting from this loose restriction.
706 *
707 * \note The overloads taking NO SequencePolicy leave the choice to the implementation. Today they
708 * search sequentially, but that is NOT a promise: it may become eSeq, ePar, eParUnseq or
709 * eUnseq (SIMD), chosen by heuristic (element count, backend, ...).
710 *
711 * So 'that' (and 'equalsComparer') must be safe under ANY of them:
712 *
713 * o No unsynchronized side effects on shared state - it may run on several threads at once.
714 * Note this is the requirement people most often miss on Find (), because a predicate
715 * that records what it saw looks harmless.
716 * o No dependence on the ORDER elements are visited in, on which thread visits them, or on
717 * HOW MANY times it is called - a parallel search may keep testing elements after another
718 * thread has already matched, so it can be called more times than a sequential scan would.
719 * o It must NOT throw. Every policy-taking std algorithm calls std::terminate () when an
720 * element access function exits via an exception, rather than propagating it - see
721 * [algorithms.parallel.exceptions].
722 * o Under the unsequenced policies (eUnseq / eParUnseq) it must additionally avoid
723 * vectorization-unsafe operations - allocation, and taking a lock. Calls may interleave
724 * WITHIN a single thread there, so a mutex can deadlock against itself.
725 *
726 * If your predicate cannot meet all of that, pass Execution::SequencePolicy::eSeq explicitly.
727 * That is not a workaround - it is how you state the sequential semantics are load-bearing.
728 *
729 * To pass a policy with the DEFAULT comparer, name the comparer: Find (v, equal_to<T>{}, ePar).
730 * There is deliberately no Find (v, seq) shorthand - it would read as an overload set where
731 * the second argument means two unrelated things.
732 */
736 nonvirtual Iterator<T> Find (THAT_FUNCTION&& that, Execution::SequencePolicy seq) const;
737 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
738 nonvirtual Iterator<T> Find (Common::ArgByValueType<T> v, EQUALS_COMPARER&& equalsComparer = {}) const;
739 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
741 template <predicate<T> THAT_FUNCTION>
742 nonvirtual Iterator<T> Find (const Iterator<T>& startAt, THAT_FUNCTION&& that) const;
743 template <predicate<T> THAT_FUNCTION>
745 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
746 nonvirtual Iterator<T> Find (const Iterator<T>& startAt, Common::ArgByValueType<T> v, EQUALS_COMPARER&& equalsComparer = {}) const;
747 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
748 nonvirtual Iterator<T> Find (const Iterator<T>& startAt, Common::ArgByValueType<T> v, EQUALS_COMPARER&& equalsComparer,
750
751 public:
752 /**
753 * As<CONTAINER_OF_T> () can be used to easily map an iterable to another container
754 * (for example STL container) which supports begin/end iterator constructor. This is
755 * really just a shorthand for
756 * CONTAINER_OF_T{this->begin (), this->end ()};
757 *
758 * Note - this also works with (nearly all) of the Stroika containers as well
759 * (e.g. Set<T> x; x.As<Sequence<T>> ());
760 *
761 * \em Design Note:
762 * We chose NOT to include an overload taking iterators because there was no connection between
763 * 'this' and the used iterators, so you may as well just directly call CONTAINER_OF_T{it1, it2}.
764 */
765 template <IIterableOfFrom<T> CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
767
768 public:
769 /**
770 * \brief Find the Nth element of the Iterable<>
771 *
772 * if n < 0, treated as from the end, so actual index = size () + n
773 *
774 * \par Example Usage
775 * \code
776 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
777 * EXPECT_EQ (c.Nth (1), 2);
778 * EXPECT_EQ (c.Nth (-1), 6);
779 * \endcode
780 *
781 * \pre n < size () // for size_t overload
782 * \pre n < size () and n > -size() // for ptrdiff_t overload
783 */
784 nonvirtual T Nth (ptrdiff_t n) const;
785
786 public:
787 /**
788 * \brief Find the Nth element of the Iterable<>, but allow for n to be out of range, and just return argument default-value
789 *
790 * \par Example Usage
791 * \code
792 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
793 * EXPECT_EQ (c.NthValue (1), 2);
794 * EXPECT_EQ (c.NthValue (99), int{});
795 * \endcode
796 *
797 */
798 nonvirtual T NthValue (ptrdiff_t n, ArgByValueType<T> defaultValue = {}) const;
799
800 public:
801 /**
802 * \brief produce a subset of this iterable where argument function returns true
803 *
804 * BASED ON Microsoft .net Linq.
805 *
806 * @aliases Filter
807 * @aliases AllThat, AllOf
808 *
809 * This returns either an Iterable<T>, or a concrete container (provided template argument). If returning
810 * just an Iterable<T>, then the result is lazy evaluated. If a concrete container is provided, its fully constructed
811 * when Where returns.
812 *
813 * \par Example Usage
814 * \code
815 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
816 * EXPECT_TRUE (c.Where ([] (int i) { return i % 2 == 0; }).SequentialEquals (Iterable<int> { 2, 4, 6 }));
817 * \endcode
818 *
819 * \note Could have been called EachWith, EachWhere, EachThat (), AllThat, AllWhere, Filter, or SubsetWhere.
820 *
821 * \note This is NEARLY IDENTICAL to the Map<RESULT_CONTAINER> function - where it uses its optional returning filter function.
822 * Please where cannot be used to transform the shape of the data (e.g. projections) whereas Map() can.
823 * But for the filter use case, this is a bit terser, so maybe still useful --LGP 2022-11-15
824 *
825 * \see See also Map<RESULT_CONTAINER,ELEMENT_MAPPER> ()
826 */
827#if qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
828 template <typename RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
830 template <typename RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
832#else
833 template <derived_from<Iterable<T>> RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
835 template <derived_from<Iterable<T>> RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
837#endif
838
839 public:
840 /**
841 * BASED ON Microsoft .net Linq.
842 *
843 * This returns an Iterable<T> that contains just the subset of the items which are distinct (equality comparer)
844 *
845 * \par Example Usage
846 * \code
847 * Iterable<int> c { 1, 2, 2, 5, 9, 4, 5, 6 };
848 * EXPECT_TRUE (c.Distinct ().SetEquals (Iterable<int> { 1, 2, 4, 5, 6, 9 }));
849 * \endcode
850 *
851 * @todo need overloads taking lambda that projects
852 * @todo for now use builtin stl set to accumulate, but need flexibility on where compare and maybe also redo with hash?
853 */
854 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
855 nonvirtual Iterable<T> Distinct (EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
856 template <typename RESULT, Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<RESULT>>
857 nonvirtual Iterable<RESULT> Distinct (const function<RESULT (ArgByValueType<T>)>& extractElt,
858 EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
859
860 public:
861 /**
862 * \brief functional API which iterates over all members of an Iterable, applies a map function to each element, and collects the results in a new Iterable
863 *
864 * This is like the map() function in so many other languages, like lisp, JavaScript, etc, **not** like the STL::map class.
865 *
866 * The transformation may be a projection, or complete transformation. If the 'extract' function returns optional<RESULT_COLLECTION::value_type>, then a missing
867 * value is treated as removal from the source list (in the resulting generated list).
868 *
869 * \note - @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
870 * as it does essentially the same thing. It can be used to completely transform a container of one thing
871 * into a (possibly smaller) container of something else by iterating over all the members, applying a function, and
872 * (optionally) appending the result of that function to the new container.
873 *
874 * \note Prior to Stroika v3.0d5, this template look 2 template parameters, the first an element type and the second the collection to be produced.
875 * But since that release, we just take the second parameter (as first) - and infer the RESULT_ELELMENT_TYPE.
876 *
877 * \note Prior to Stroika v2.1.10, this was called Select ()
878 *
879 * \note - The overloads returning Iterable<RESULT> do NOT IMMEDIATELY traverse its argument, but uses @see CreateGenerator - to create a new iterable that dynamically pulls
880 * from 'this' Iterable<>'.
881 *
882 * The overloads returning RESULT_CONTAINER DO however immediately construct RESULT_CONTAINER, and fill it in the the result
883 * of traversal before Map () returns.
884 *
885 * \note This can be used to filter data, but if that is the only goal, 'Where' is a better choice. If the argument function
886 * returns optional<THE RETURN TYPE> - then only accumulate those that are returned with has_value () (so also can be used to filter).
887 *
888 * \par Example Usage
889 * \code
890 * Iterable<pair<int,char>> c { {1, 'a'}, {2, 'b'}, {3, 'c'} };
891 * EXPECT_TRUE (c.Map<Iterable<int>> ([] (pair<int,char> p) { return p.first; }).SequentialEquals (Iterable<int> { 1, 2, 3 }));
892 * \endcode
893 *
894 * This can also easily be used to TRANSFORM an iterable.
895 * \par Example Usage
896 * \code
897 * Iterable<int> c { 3, 4, 7 };
898 * EXPECT_TRUE (c.Map<Iterable<String>> ([] (int i) { return Characters::Format ("{}"_f, i); }).SequentialEquals (Iterable<String> { "3", "4", "7" }));
899 * \endcode
900 *
901 * \par Example Usage
902 * or transform into another container type
903 * \code
904 * Iterable<int> c { 3, 4, 7 };
905 * EXPECT_TRUE ((c.Map<vector<String>> ([] (int i) { return Characters::Format ("{}"_f, i); }) == vector<String>{"3", "4", "7"}));
906 * \endcode
907 *
908 * \par Example Usage
909 * \code
910 * void ExpectedMethod (const Request* request, const Set<String>& methods, const optional<String>& fromInMessage)
911 * {
912 * String method{request->GetHTTPMethod ()};
913 * Set<String> lcMethods = methods.Map<Iterable<String>> ([](const String& s) { return s.ToLowerCase (); });
914 * if (not methods.Contains (method.ToLowerCase ())) {
915 * ...
916 * \endcode
917 *
918 * Overload which returns optional<RESULT> and nullopt interpreted as skipping that element
919 *
920 * \par Example Usage
921 * Filtering a list example:
922 * \code
923 * // GetAssociatedContentType -> optional<String> - skip items that are 'missing'
924 * possibleFileSuffixes.Map<Set<InternetMediaType>> ([&] (String suffix) -> optional<InternetMediaType> { return r.GetAssociatedContentType (suffix); })
925 * \endcode
926 *
927 * \note This could have been written as one function/overload, but then for the RESULT_CONTAINER=Iterable<T> case
928 * we would be forced to uselessly create a bogus Iterable, and then throw it away.
929 */
930 template <ranges::range RESULT_CONTAINER = Iterable<T>, invocable<T> ELEMENT_MAPPER>
932 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
934 template <ranges::range RESULT_CONTAINER = Iterable<T>, invocable<T> ELEMENT_MAPPER>
936 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
938
939 public:
940 /**
941 * \brief Walk the entire list of items, and use the argument 'op' to combine (reduce) items to a resulting single item.
942 *
943 * \see https://en.wikipedia.org/wiki/Reduction_operator
944 * \see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
945 * \see https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?redirectedfrom=MSDN&view=net-7.0#overloads
946 *
947 * @aliases Accumulate
948 *
949 * \note This was called Accumulate in Stroika up until 2.1.10
950 *
951 * \par Example Usage
952 * \code
953 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
954 * EXPECT_TRUE (c.Reduce ([] (T lhs, T rhs) { return lhs + rhs; }) == 24);
955 * \endcode
956 *
957 * \par Implementation As if:
958 * \code
959 * optional<RESULT_TYPE> result;
960 * for (const auto& i : *this) {
961 * if (result) {
962 * result = op (*result, i);
963 * }
964 * else {
965 * result = i;
966 * }
967 * }
968 * \endcode
969 *
970 * \note op () is called with the ACCUMULATOR as its first argument and the next element as
971 * its second - the same way round as std::accumulate and as Join ()'s combiner. This
972 * only matters for a non-commutative op, but then it matters entirely.
973 *
974 * \note Changed in Stroika v3.0d24: op () used to be called as op (element, accumulator),
975 * which silently reversed non-commutative operations - Sum () over an Iterable<String>
976 * of {A, B, C} returned "CBA". Code that passes a commutative op (the overwhelmingly
977 * common case - anything arithmetic, min, max) is unaffected.
978 *
979 * \note returns nullopt if empty list
980 *
981 * See:
982 * @see ReduceValue
983 * @see Join
984 * @see Sum
985 * @see SumValue
986 */
987 template <typename REDUCED_TYPE = T>
989
990 public:
991 /**
992 * @see @Reduce, but if value is missing, returns defaultValue arg or {}
993 */
994 template <typename REDUCED_TYPE = T>
997
998 public:
999 /**
1000 * kDefaultToStringConverter encapsulates the algorithm used to map T objects to printable strings. As this is
1001 * mainly used for debugging, it defaults to using Characters::ToString() - and so maybe lossy.
1002 *
1003 * For plain Strings - however, it just uses Common::Identity (no mapping). So that when used in Join - you get
1004 * no changes to the argument strings (by default - easy to pass in lambda todo what you want to Join).
1005 *
1006 * \note - logically - kDefaultToStringConverter takes no template parameter, but in practical use, it must
1007 * just to postpone the evaluation of its type argument and avoid a direct dependency on the String module,
1008 * which in turn depends on this module.
1009 */
1010 template <same_as<Characters::String> RESULT_T = Characters::String>
1011 static inline const function<RESULT_T (T)> kDefaultToStringConverter = [] () -> function<Characters::String (T)> {
1013 return Common::Identity{};
1014 }
1015 else {
1016 return Characters::UnoverloadedToString<T>;
1017 }
1018 }();
1019
1020 public:
1021 /**
1022 * \brief ape the JavaScript/python 'join' function - take the parts of 'this' iterable and combine them into a new object (typically a string)
1023 *
1024 * This Join () API - if you use the template, is fairly generic and lets the caller iterate over subelements of this iterable, and
1025 * combine them into a new thing (@see Reduce - it is similar but more general).
1026 *
1027 * For the very common case of accumulating objects into a String, there are additional (stringish) overloads that more closely mimic
1028 * what you can do in JavaScript/python.
1029 *
1030 * Gist of arguments
1031 * o convertToResult: - OPTIONAL converter from T to String
1032 * o combiner: - OPTIONAL thing that joins two RESULT_T (result of above covertToResult - typically String)
1033 * and combiner MAYBE replaced with String (separator and optionally finalStringSeparator)
1034 *
1035 * \note The String returning overload converts to String with kDefaultToStringConverter (Characters::ToString - mostly), so this may not be
1036 * a suitable conversion in all cases (mostly intended for debugging or quick cheap display)
1037 *
1038 * \par Example Usage
1039 * \code
1040 * Iterable<InternetAddress> c{IO::Network::V4::kLocalhost, IO::Network::V4::kAddrAny};
1041 * EXPECT_EQ (c.Join (), "localhost, INADDR_ANY");
1042 * EXPECT_EQ (c.Join ("; "), "localhost; INADDR_ANY");
1043 * \endcode
1044 *
1045 * \par Example Usage
1046 * \code
1047 * const Iterable<String> kT1_{"a", "b"};
1048 * const Iterable<String> kT2_{"a", "b", "c"};
1049 * EXPECT_EQ (kT1_.Join (Characters::UnoverloadedToString<String>), "'a', 'b'");
1050 * EXPECT_EQ (kT1_.Join (Iterable<String>::kDefaultToStringConverter<String>), kT1_.Join ());
1051 * // Common::Identity{} produces no transformation, and the combiner function just directly concatenates with no separator
1052 * EXPECT_EQ (kT1_.Join (Common::Identity{}, [] (auto l, auto r, bool) { return l + r; }), "ab");
1053 * EXPECT_EQ (kT1_.Join (), "a, b");
1054 * EXPECT_EQ (kT1_.Join (" "), "a b");
1055 * EXPECT_EQ (kT1_.Join (", ", " and "), "a and b");
1056 * EXPECT_EQ (kT2_.Join (", ", " and "), "a, b and c");
1057 * EXPECT_EQ (kT2_.Join ([] (auto i) { return i.ToUpperCase (); }), "A, B, C");
1058 * EXPECT_EQ (kT2_.Join ([] (auto i) { return i.ToUpperCase (); }, "; "sv, " and "sv), "A; B and C");
1059 * \endcode
1060 *
1061 * See:
1062 * @see Accumulate
1063 */
1064#if qCompilerAndStdLib_template_SubstDefaultTemplateParamVariableTemplate_Buggy
1065 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<RESULT_T>),
1066 invocable<RESULT_T, RESULT_T, bool> COMBINER = decltype (Characters::kDefaultStringCombiner)>
1071#else
1072 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<>),
1073 invocable<RESULT_T, RESULT_T, bool> COMBINER = decltype (Characters::kDefaultStringCombiner)>
1078#endif
1079#if qCompilerAndStdLib_template_optionalDeclareIncompleteType_Buggy
1080 nonvirtual Characters::String Join (const Characters::String& separator) const;
1082 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
1083 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult, const RESULT_T& separator) const
1085 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
1088#else
1090 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
1093#endif
1094
1095 public:
1096 /**
1097 * BASED ON Microsoft .net Linq.
1098 *
1099 * This returns an Iterable<T> with a subset of data after skipping the argument number of items.
1100 * If the number of items skipped is greater or equal to the length of the original Iterable, then
1101 * an empty Iterable is returned.
1102 *
1103 * \par Example Usage
1104 * \code
1105 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1106 * EXPECT_TRUE (c.Skip (3).SequentialEquals (Iterable<int> { 4, 5, 6 }));
1107 * \endcode
1108 *
1109 * @see https://msdn.microsoft.com/en-us/library/bb358985%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
1110 * @Take
1111 */
1112 nonvirtual Iterable<T> Skip (size_t nItems) const;
1113
1114 public:
1115 /**
1116 * BASED ON Microsoft .net Linq.
1117 *
1118 * This returns an Iterable<T> with up to nItems taken from the front of this starting iterable. If this Iterable
1119 * is shorter, Take () returns just the original Iterable
1120 *
1121 * \par Example Usage
1122 * \code
1123 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1124 * EXPECT_TRUE (c.Take (3).SequentialEquals (Iterable<int> { 1, 2, 3 }));
1125 * \endcode
1126 *
1127 * @see https://msdn.microsoft.com/en-us/library/bb503062(v=vs.110).aspx
1128 * @Skip
1129 */
1130 nonvirtual Iterable<T> Take (size_t nItems) const;
1131
1132 public:
1133 /**
1134 * This returns an Iterable<T> based on the current iterable, with the subset from position from to to.
1135 * If some items don't exist, the resulting list is shortened (not an assertion error).
1136 * Item at from is included in the output, but item 'to' is not included.
1137 *
1138 * \par Example Usage
1139 * \code
1140 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1141 * EXPECT_TRUE (c.Slice (3, 5).SequentialEquals ({ 4, 5 }));
1142 * \endcode
1143 *
1144 * \pre from <= to
1145 *
1146 * \note equivalent to Skip (from).Take (to-from)
1147 *
1148 * @see https://www.w3schools.com/jsref/jsref_slice_array.asp (EXCEPT FOR NOW - we don't support negative indexes or optional args; maybe do that for SEQUENCE subclass?)
1149 * @see Take
1150 * @see Slice
1151 */
1152 nonvirtual Iterable<T> Slice (size_t from, size_t to) const;
1153
1154 public:
1155 /**
1156 * \brief return the top/largest value (or the top N values) from this Iterable<T>
1157 *
1158 * The overloads WITHOUT an 'n' argument return the single top element, as an optional<T> which is
1159 * nullopt iff the Iterable is empty. The overloads WITH an 'n' return the top n, as an Iterable<T>
1160 * (n is allowed to exceed size (), in which case you just get everything, ordered).
1161 *
1162 * Provide a function object that says how you want to compare the 'T' elements; 'top' means the
1163 * element that would come FIRST in that order. It defaults to std::greater<T>, so by default 'top'
1164 * is the largest.
1165 *
1166 * \em Performance:
1167 * let S = this->size();
1168 * o no 'n' argument: O(S)
1169 * o with 'n': O(S) * ln (N) ; so S*log(S) if you get all of them, but if you just
1170 * need the top three, its O(S)
1171 *
1172 * \par Example Usage
1173 * \code
1174 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1175 * EXPECT_TRUE (c.Top () == 38); // optional<int>
1176 * EXPECT_TRUE (c.Top (std::less<int>{}) == 3); // 'first' by the given order
1177 * EXPECT_TRUE (Iterable<int>{}.Top () == nullopt); // empty ==> nullopt
1178 * EXPECT_TRUE (c.Top (2).SequentialEquals ({38, 9}));
1179 * EXPECT_TRUE (c.Top (2, std::greater<int>{}).SequentialEquals ({38, 9})); // same as previous line
1180 * EXPECT_TRUE (c.Top (3, std::less<int>{}).SequentialEquals ({3, 3, 5}));
1181 * \endcode
1182 *
1183 * \note ***NOT BACKWARD COMPATIBLE*** - before Stroika v3.0d24, the no-'n' overloads returned an
1184 * Iterable<T> of EVERY element in order (ie they treated the missing 'n' as infinity, not as
1185 * one). To recover that behavior, pass an 'n' larger than the container - eg
1186 * Top (numeric_limits<size_t>::max ()) - or just use OrderBy ().
1187 *
1188 * \note If several elements tie for top (compare equal under 'cmp'), which one you get is
1189 * unspecified, and the no-'n' and 'n' overloads may pick differently: Top () yields the
1190 * first such element in iteration order, whereas the Top (n, ...) overloads sort and so may
1191 * yield any of them. Don't rely on Top () and Top (1) naming the same element.
1192 *
1193 * \note Uses IPotentiallyComparer instead of IInOrderComparer since from context, if you pass in a lambda, it
1194 * should be clear about intent.
1195 */
1196 nonvirtual optional<T> Top () const;
1197 nonvirtual Iterable<T> Top (size_t n) const;
1198 template <Common::IPotentiallyComparer<T> COMPARER>
1199 nonvirtual optional<T> Top (COMPARER&& cmp) const;
1200 template <Common::IPotentiallyComparer<T> COMPARER>
1201 nonvirtual Iterable<T> Top (size_t n, COMPARER&& cmp) const;
1202
1203 public:
1204 /**
1205 * BASED ON Microsoft .net Linq.
1206 *
1207 * \par Example Usage
1208 * \code
1209 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1210 * EXPECT_TRUE (c.OrderBy ().SequentialEquals ({ 3, 3, 5, 5, 9, 38 }));
1211 * \endcode
1212 *
1213 * \par Example Usage
1214 * \code
1215 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1216 * EXPECT_TRUE (c.OrderBy ([](int lhs, int rhs) -> bool { return lhs < rhs; }).SequentialEquals ({ 3, 3, 5, 5, 9, 38 }));
1217 * \endcode
1218 *
1219 * \note The overload taking NO SequencePolicy leaves the choice to the implementation. It sorts
1220 * sequentially today, but that is NOT a promise - it may become eSeq, ePar, eParUnseq or
1221 * eUnseq (SIMD), most likely chosen on element count once the crossover has been measured.
1222 *
1223 * So when you use that overload, your comparer must be fit to run under ANY of them:
1224 *
1225 * o PURE - callable concurrently, with no side effects on shared state, and no dependence
1226 * on how many times, in what order, or on which thread it is called. A sort calls the
1227 * comparer an unspecified number of times even sequentially; parallel just makes that
1228 * more visible.
1229 * o NON-THROWING. This one is easy to miss, and it is not implied by purity: eSeq sorts
1230 * via the plain stable_sort (), where an exception from your comparer propagates
1231 * normally, but every parallel policy goes through a policy-taking std algorithm, and
1232 * there an exception escaping an element access function calls std::terminate () -
1233 * see [algorithms.parallel.exceptions]. A pure comparer can still throw (bad_alloc
1234 * comparing Strings, say). Nothing warns you; the process just dies.
1235 * o Under the unsequenced policies (eUnseq / eParUnseq), additionally free of
1236 * vectorization-unsafe operations - allocation, and taking a lock. Calls may interleave
1237 * WITHIN a single thread there, so a mutex can deadlock against itself.
1238 *
1239 * If your comparer cannot meet all of that, pass Execution::SequencePolicy::eSeq explicitly.
1240 * That is not a workaround - it is how you say the sequential semantics are load-bearing, and
1241 * it keeps working when the unspecified overload starts choosing for itself.
1242 *
1243 * \note Measurements so far say sequential, which is why the unspecified overload picks it: ePar
1244 * cost 2.08x on Sequence<int> and 1.81x on Iterable<int> (run 'Test52 --show --orderby-probe').
1245 * That is N=1000, one machine, int elements - parallel should win at some larger N, but the
1246 * crossover is UNMEASURED, so there is no honest threshold to code yet. A size sweep is what
1247 * would replace this eSeq with a real heuristic.
1248 *
1249 * \note This performs a stable sort (preserving the relative order of items that compare equal).
1250 * That maybe less performant than a regular (e.g. quicksort) but works better as a default, in most cases, as it allows combining multi-level sorts.
1251 *
1252 * \note The concrete backend of the RESULT is unspecified, and will generally not be the receiver's -
1253 * unlike Where ()/Map (), which CloneEmpty () so the result keeps the receiver's rep type.
1254 * Sorting has to materialize a contiguous buffer regardless, so there is nothing to preserve.
1255 * Do not depend on which; construct the backend you want from the result if it matters.
1256 *
1257 * @aliases Sort ()
1258 *
1259 * \note Should be of type IInOrderComparer, but not required - for convenience of use (so can be used with any lambda functor)
1260 *
1261 * See:
1262 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.orderby(v=vs.110).aspx
1263 * @see IsOrderedBy ()
1264 *
1265 * \post result.IsOrderedBy (inorderComparer);
1266 */
1267 template <Common::IPotentiallyComparer<T> INORDER_COMPARER_TYPE = less<T>>
1269 template <Common::IPotentiallyComparer<T> INORDER_COMPARER_TYPE = less<T>>
1271
1272 public:
1273 /**
1274 * @aliases IsSorted ()
1275 *
1276 * \see
1277 * OrderBy ()
1278 */
1279 template <Common::IPotentiallyComparer<T> INORDER_COMPARER_TYPE = less<T>>
1281
1282 public:
1283 /**
1284 * \brief return first element in iterable, or if 'that' specified, first where 'that' is true, (or return nullopt if none)
1285 *
1286 * @see Find () - but Find () returns an Iterator<>, and does NOT promise the FIRST match; that
1287 * guarantee is what First () is for.
1288 *
1289 * \par Example Usage
1290 * \code
1291 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1292 * EXPECT_EQ (*c.First (), 3);
1293 * EXPECT_EQ (*c.First ([](int i){ return i % 2 == 0;}), 38);
1294 * \endcode
1295 *
1296 * \par Example Usage
1297 * \code
1298 * Collection<SomeStruct> c;
1299 * if (optional<SomeStruct> o = c.First ([=](SomeStruct smi) { return smi.fID == substanceId; })) {
1300 * something_with_o (o);
1301 * }
1302 * \endcode
1303 *
1304 * \note
1305 * BASED ON Microsoft .net Linq.
1306 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.first(v=vs.110).aspx
1307 */
1308 nonvirtual optional<T> First () const;
1309 template <invocable<T> F>
1310 nonvirtual optional<T> First (F&& that) const
1311 requires (convertible_to<invoke_result_t<F, T>, bool>);
1312 template <typename RESULT_T = T>
1313 nonvirtual optional<RESULT_T> First (const function<optional<RESULT_T> (ArgByValueType<T>)>& that) const;
1314
1315 public:
1316 /**
1317 * \brief return first element in iterable provided default
1318 *
1319 * \par Example Usage
1320 * \code
1321 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1322 * EXPECT_EQ (c.FirstValue (), 3);
1323 * \endcode
1324 *
1325 * \note
1326 * BASED ON Microsoft .net Linq. (FirstOrDefault)
1327 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.firstordefault(v=vs.110).aspx
1328 */
1329 nonvirtual T FirstValue (ArgByValueType<T> defaultValue = {}) const;
1330 template <invocable<T> F>
1331 nonvirtual T FirstValue (F&& that, ArgByValueType<T> defaultValue = {}) const
1332 requires (convertible_to<invoke_result_t<F, T>, bool>);
1333
1334 public:
1335 /**
1336 * \brief return last element in iterable, or if 'that' specified, last where 'that' is true, (or return missing)
1337 *
1338 * \par Example Usage
1339 * \code
1340 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1341 * EXPECT_EQ (*c.Last (), 5);
1342 * EXPECT_EQ (*c.Last ([](int i){ return i % 2 == 0;}), 38);
1343 * \endcode
1344 *
1345 * \note
1346 * BASED ON Microsoft .net Linq. (Last)
1347 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.last(v=vs.110).aspx
1348 */
1349 nonvirtual optional<T> Last () const;
1350 template <invocable<T> F>
1351 nonvirtual optional<T> Last (F&& that) const
1352 requires (convertible_to<invoke_result_t<F, T>, bool>);
1353 template <typename RESULT_T = T>
1354 nonvirtual optional<RESULT_T> Last (const function<optional<RESULT_T> (ArgByValueType<T>)>& that) const;
1355
1356 public:
1357 /**
1358 * BASED ON Microsoft .net Linq. (LastOrDefault)
1359 *
1360 * \par Example Usage
1361 * \code
1362 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1363 * EXPECT_EQ (c.LastValue (), 5);
1364 * \endcode
1365 *
1366 * See:
1367 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.lastordefault(v=vs.110).aspx
1368 */
1369 nonvirtual T LastValue (ArgByValueType<T> defaultValue = {}) const;
1370 template <invocable<T> F>
1371 nonvirtual T LastValue (F&& that, ArgByValueType<T> defaultValue = {}) const
1372 requires (convertible_to<invoke_result_t<F, T>, bool>);
1373
1374 public:
1375 /**
1376 * \brief return true iff argument predicate returns true for each element of the iterable
1377 *
1378 * \par Example Usage
1379 * \code
1380 * Iterable<int> c { 3, 5, 9, 3, 5 };
1381 * EXPECT_TRUE (c.All ([](int i){ return i % 2 == 1;}));
1382 * \endcode
1383 *
1384 * \note
1385 * BASED ON Microsoft .net Linq. (Last)
1386 * @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.all?view=netframework-4.7.2
1387 *
1388 * @see also Iterable<T>::Where ()
1389 */
1390 nonvirtual bool All (const function<bool (ArgByValueType<T>)>& testEachElt) const;
1391
1392 public:
1393 /**
1394 * BASED ON Microsoft .net Linq.
1395 *
1396 * \par Example Usage
1397 * \code
1398 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1399 * EXPECT_TRUE (c.Min () == 1);
1400 * \endcode
1401 *
1402 * \note returns nullopt if empty list
1403 *
1404 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return min (lhs, rhs); })
1405 *
1406 * See:
1407 * https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
1408 * @Max
1409 */
1410 nonvirtual optional<T> Min () const;
1411
1412 public:
1413 /**
1414 * @see @Max
1415 */
1416 template <typename RESULT_TYPE = T>
1418
1419 public:
1420 /**
1421 * BASED ON Microsoft .net Linq.
1422 *
1423 * EXAMPLE:
1424 * \code
1425 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1426 * EXPECT_TRUE (c.Max () == 6);
1427 * \endcode
1428 *
1429 * \note returns nullopt if empty list
1430 *
1431 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return max (lhs, rhs); })
1432 *
1433 * See:
1434 * https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
1435 * @Min
1436 */
1437 nonvirtual optional<T> Max () const;
1438
1439 public:
1440 /**
1441 * @see @Max
1442 */
1443 template <typename RESULT_TYPE = T>
1445
1446 public:
1447 /**
1448 * BASED ON Microsoft .net Linq.
1449 *
1450 * \par Example Usage
1451 * \code
1452 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
1453 * EXPECT_EQ (c.Mean (), 4);
1454 * \endcode
1455 *
1456 * \note returns nullopt if empty list
1457 *
1458 * AKA "Average"
1459 *
1460 * See:
1461 * https://msdn.microsoft.com/en-us/library/bb548647(v=vs.100).aspx
1462 */
1463 template <typename RESULT_TYPE = T>
1464 nonvirtual optional<RESULT_TYPE> Mean () const;
1465
1466 public:
1467 /**
1468 * @see @Mean
1469 */
1470 template <typename RESULT_TYPE = T>
1472
1473 public:
1474 /**
1475 * BASED ON Microsoft .net Linq.
1476 *
1477 * \par Example Usage
1478 * \code
1479 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
1480 * EXPECT_TRUE (c.Sum () == 24);
1481 * \endcode
1482 *
1483 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return lhs + rhs; })
1484 *
1485 * \note returns nullopt if empty list
1486 *
1487 * See:
1488 * https://msdn.microsoft.com/en-us/library/system.linq.enumerable.sum(v=vs.110).aspx
1489 */
1490 template <typename RESULT_TYPE = T>
1491 nonvirtual optional<RESULT_TYPE> Sum () const;
1492
1493 public:
1494 /**
1495 * @see @Sum
1496 */
1497 template <typename RESULT_TYPE = T>
1499
1500 public:
1501 /**
1502 * \par Example Usage
1503 * \code
1504 * Iterable<int> c { 1, 2, 9, 4, 5, 3 };
1505 * EXPECT_TRUE (NearlyEquals (c.Median (), 3.5));
1506 * \endcode
1507 *
1508 * \note returns nullopt if empty list
1509 *
1510 * \note Should be of type IInOrderComparer, but not required - for convenience of use (so can be used with any lambda functor)
1511 * \todo probably TIGHTEN THIS - and require ITotallyOrdering.... - so can use either less compare or strong compare function.
1512 */
1513 template <constructible_from<T> RESULT_TYPE = T, Common::IPotentiallyComparer<RESULT_TYPE> INORDER_COMPARE_FUNCTION = less<RESULT_TYPE>>
1515
1516 public:
1517 /**
1518 * @see @Median
1519 */
1520 template <constructible_from<T> RESULT_TYPE = T>
1522
1523 public:
1524 /**
1525 * Return this iterable n (count) times. count may be zero, or any other unsigned integer.
1526 * Repeat (0) returns an empty list, and Repeat (1) returns *this;
1527 *
1528 * Similar to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.repeat?view=netcore-3.1
1529 *
1530 * \par Example Usage
1531 * \code
1532 * Iterable<int> c{1};
1533 * EXPECT_TRUE (c.Repeat (5).SequentialEquals ({1, 1, 1, 1, 1}));
1534 * \endcode
1535 */
1536 nonvirtual Iterable<T> Repeat (size_t count) const;
1537
1538 public:
1539 /**
1540 * \brief Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any values in iterable
1541 *
1542 * \note
1543 * BASED ON Microsoft .net Linq. (Last)
1544 * @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.7.2#System_Linq_Enumerable_Any__1_System_Collections_Generic_IEnumerable___0__System_Func___0_System_Boolean__
1545 *
1546 * \note @see Count
1547 * \note @see Where
1548 * @aliases AnyThat (predicate)
1549 */
1550 nonvirtual bool Any () const;
1551 nonvirtual bool Any (const function<bool (ArgByValueType<T>)>& includeIfTrue) const;
1552
1553 public:
1554 /**
1555 * \brief with no args, same as size, with function filter arg, returns number of items that pass.
1556 *
1557 * \note
1558 * BASED ON Microsoft .net Linq. (Count)
1559 * @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.count?view=net-6.0
1560 *
1561 * \note Count/1 same as Where (i).size ();
1562 * \note @see Any
1563 */
1564 nonvirtual size_t Count () const;
1565 nonvirtual size_t Count (const function<bool (ArgByValueType<T>)>& includeIfTrue) const;
1566
1567 public:
1568 /**
1569 * \brief STL-ish alias for size() - really in STL only used in string, I think, but still makes sense as an alias.
1570 */
1571 nonvirtual size_t length () const;
1572
1573 protected:
1574 /**
1575 * @see Memory::SharedByValueSupport::SharingState
1576 *
1577 * Don't call this lightly. This is just meant for low level or debugging, and for subclass optimizations
1578 * based on the state of the shared common object.
1579 */
1581
1582 private:
1583 static shared_ptr<_IRep> Clone_ (const _IRep& rep);
1584
1585 private:
1586 template <typename CONTAINER_OF_T>
1587 static Iterable<T> mk_ (CONTAINER_OF_T&& from)
1589
1590 protected:
1591 /*
1592 * \brief Lazy-copying smart pointer mostly used by implementors (can generally be ignored by users).
1593 * However, protected because manipulation needed in some subclasses (rarely) - like _GetWritableRepAndPatchAssociatedIterator.
1594 */
1596
1597 protected:
1598 template <typename REP_SUB_TYPE = _IRep>
1599 class _SafeReadRepAccessor;
1600
1601 protected:
1602 template <typename REP_SUB_TYPE = _IRep>
1603 class _SafeReadWriteRepAccessor;
1604
1605 protected:
1606 /**
1607 * Rarely access in subclasses, but its occasionally needed, like in UpdatableIterator<T>
1608 */
1610
1611 protected:
1612 Debug::AssertExternallySynchronizedChecker _fThisAssertExternallySynchronized;
1613
1614 public:
1615 template <typename SHARED_T>
1616 using PtrImplementationTemplate [[deprecated ("Since Stroika v3.0d1 - use shared_ptr directly")]] = shared_ptr<SHARED_T>;
1617 template <typename SHARED_T, typename... ARGS_TYPE>
1618 [[deprecated ("Since Stroika v3.0d1 - use Memory::MakeSharedPtr directly")]] static shared_ptr<SHARED_T> MakeSmartPtr (ARGS_TYPE&&... args)
1619 {
1620 return Memory::MakeSharedPtr<SHARED_T> (forward<ARGS_TYPE> (args)...);
1621 }
1622 template <typename SHARED_T>
1623 using enable_shared_from_this_PtrImplementationTemplate [[deprecated ("Since Stroika v3.0d1")]] = std::enable_shared_from_this<SHARED_T>;
1624
1625 protected:
1626 using _IterableRepSharedPtr [[deprecated ("Since Stroika v3.0d1 use shared_ptr<_IRep> directly")]] = shared_ptr<_IRep>;
1627 using _IteratorRepSharedPtr [[deprecated ("Since Stroika v3.0d1 use unique_ptr<typename Iterator<T>::IRep> directly")]] =
1629 };
1630
1631#if qCompilerAndStdLib_lambdas_in_unevaluatedContext_warning_Buggy
1632 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wsubobject-linkage\"")
1633#endif
1634
1635 /**
1636 * _SafeReadRepAccessor is used by Iterable<> subclasses to assure thread safety. It takes the
1637 * 'this' object, and captures a const reference to the internal 'REP'.
1638 *
1639 * For DEBUGGING (catching races) purposes, it also locks the Debug::AssertExternallySynchronizedChecker,
1640 * so that IF this object is accessed illegally by other threads while in use (this use), it will
1641 * be caught.
1642 *
1643 * \note _SafeReadRepAccessor also provides type safety, in that you template in the subtype
1644 * of the REP object, and we store a single pointer, but cast to the appropriate subtype.
1645 *
1646 * This supports type safe usage because in DEBUG builds we check (AssertMember)
1647 * the dynamic type, and if you structure your code to assure a given type (say Collection<T>)
1648 * only passes in to pass class appropriately typed objects, and just use that type in
1649 * your _SafeReadRepAccessor<> use, you should be safe.
1650 *
1651 * @see _SafeReadWriteRepAccessor
1652 */
1653 template <typename T>
1654 template <typename REP_SUB_TYPE>
1656 public:
1657 _SafeReadRepAccessor () = delete;
1660 _SafeReadRepAccessor (const Iterable<T>* it) noexcept;
1661
1662 public:
1663 nonvirtual _SafeReadRepAccessor& operator= (const _SafeReadRepAccessor&) = delete;
1664 nonvirtual _SafeReadRepAccessor& operator= (_SafeReadRepAccessor&& rhs) noexcept;
1665
1666 public:
1667 nonvirtual const REP_SUB_TYPE& _ConstGetRep () const noexcept;
1668
1669 public:
1670 nonvirtual shared_ptr<REP_SUB_TYPE> _ConstGetRepSharedPtr () const noexcept;
1671
1672 private:
1673 const REP_SUB_TYPE* fConstRef_;
1674 const Iterable<T>* fIterableEnvelope_;
1675
1676#if qStroika_Foundation_Debug_AssertionsChecked
1678#endif
1679 };
1680 //static_assert (movable<Iterable<int>::_SafeReadRepAccessor<REP_SUB_TYPE>> and not copyable<Iterable<int>::_SafeReadRepAccessor<REP_SUB_TYPE>>);
1681
1682 /**
1683 * _SafeReadWriteRepAccessor is used by Iterable<> subclasses to assure thread-safety. It takes the
1684 * 'this' object, and captures a writable to the internal 'REP'.
1685 *
1686 * For DEBUGGING (catching races) purposes, it also locks the Debug::AssertExternallySynchronizedChecker,
1687 * so that IF this object is accessed illegally by other threads while in use (this use), it will
1688 * be caught.
1689 *
1690 * @see _SafeReadRepAccessor
1691 *
1692 */
1693 template <typename T>
1694 template <typename REP_SUB_TYPE>
1696 public:
1697 _SafeReadWriteRepAccessor () = delete;
1701
1702 public:
1703 nonvirtual _SafeReadWriteRepAccessor& operator= (const _SafeReadWriteRepAccessor&) = delete;
1704 nonvirtual _SafeReadWriteRepAccessor& operator= (_SafeReadWriteRepAccessor&&) noexcept;
1705
1706 public:
1707 nonvirtual const REP_SUB_TYPE& _ConstGetRep () const;
1708
1709 public:
1710 nonvirtual REP_SUB_TYPE& _GetWriteableRep ();
1711
1712 private:
1713 REP_SUB_TYPE* fRepReference_;
1714#if qStroika_Foundation_Debug_AssertionsChecked
1716 Iterable<T>* fIterableEnvelope_; // mostly saved for assertions, but also for _UpdateRep- when we lose that - we can ifdef qStroika_Foundation_Debug_AssertionsChecked this field (as we do for read accessor)
1717#endif
1718 };
1719 //static_assert (movable<Iterable<int>::_SafeReadWriteRepAccessor<REP_SUB_TYPE>> and not copyable<Iterable<int>::_SafeReadWriteRepAccessor<REP_SUB_TYPE>>);
1720
1721 /**
1722 * \brief Implementation detail for iterator implementors.
1723 *
1724 * Abstract class used in subclasses which extend the idea of Iterable.
1725 * Most abstract Containers in Stroika subclass of Iterable<T>.
1726 *
1727 * \note Design Note: weak_ptr vs. dangling pointers vs shared_from_this
1728 *
1729 * Prior to Stroika v3, we had a mixed API where we passed in a shared_ptr as argument to MakeIterator and sometimes
1730 * saved the shared_ptr, making the iterators safe if certain things changed. But not generally enuf to be useful and its
1731 * costly.
1732 *
1733 * More CORRECT would be to use a weak_ptr (in debug builds) and NO pointer in no-debug builds, but that makes the API a little awkward (may still
1734 * do/revisit - LGP 2023-07-07).
1735 *
1736 * Containers internally use fChangeCounts - in DEBUG builds - to try to assure the underlying container is not modified during iteration, and
1737 * and there are several modifying APIs that take an Iterator and return an updated Iterator to avoid this issue.
1738 *
1739 * But the main takeaway, is that Iterator<> objects must be short lived, and not used after any modification to the underlying Iterable being
1740 * iterated over.
1741 */
1742 template <typename T>
1743 class Iterable<T>::_IRep {
1744 protected:
1745 _IRep () = default;
1746
1747 public:
1748 virtual ~_IRep () = default;
1749
1750 public:
1751 /**
1752 */
1753 virtual shared_ptr<_IRep> Clone () const = 0;
1754
1755 public:
1756 /**
1757 * This returns an object owning INTERNAL POINTERS to the thing being iterated over. It's a potentially
1758 * undetected error to ever operate on the iterator after the Iterable has been modified (many Stroika classes like containers
1759 * will detect this error in debug builds).
1760 */
1762
1763 public:
1764 /**
1765 * returns the number of elements in iterable. Equivalent to (and defaults to)
1766 * i = MakeIterator, followed by counting number of iterations til the end.
1767 */
1768 virtual size_t size () const;
1769
1770 public:
1771 /**
1772 * returns the true if MakeIterator() returns an empty iterator.
1773 */
1774 virtual bool empty () const;
1775
1776 public:
1777 /**
1778 * Apply the given doToElement function to every element of the Iterable (in some arbitrary order).
1779 */
1780 virtual void Apply (const function<void (ArgByValueType<T> item)>& doToElement, Execution::SequencePolicy seq) const;
1781
1782 public:
1783 /*
1784 * \see _IRep::MakeIterator for rules about lifetime of returned Iterator<T>
1785 * Defaults to, and is equivalent to, walking the Iterable, applying 'that' function, and returning an
1786 * entry that returns true (the FIRST such entry if findFirst), or empty iterator if none does.
1787 *
1788 * \param findFirst true => MUST return the first match in iteration order.
1789 * false => MAY return any match; returning the first is still legal.
1790 *
1791 * \note 'findFirst' is a SEPARATE argument from 'seq' on purpose. Which match you get and how the
1792 * search is executed are independent questions, and folding the first into the second would
1793 * make eSeq silently mean something it does not mean in std::<execution>, where the policy
1794 * never changes WHICH element std::find_if () returns.
1795 *
1796 * \note findFirst=false is a PERMISSION, not an obligation - the first match trivially satisfies
1797 * 'any match'. So an override with nothing faster to offer may ignore the flag entirely and
1798 * remain correct; that is why every existing backend needed only a signature change.
1799 *
1800 * \note This is what lets the PUBLIC Iterable<T>::Find () promise only 'a match' while
1801 * Iterable<T>::First () still guarantees the first: First () calls this with findFirst=true
1802 * (see Iterable.inl), and the public Find () passes false. Before this argument existed the
1803 * guarantee rode on eSeq, which meant a backend could break First () just by parallelizing
1804 * what looked like a pure performance knob.
1805 */
1806 virtual Iterator<value_type> Find (bool findFirst, const function<bool (ArgByValueType<T> item)>& that, Execution::SequencePolicy seq) const;
1807
1808 public:
1809 /**
1810 * Find_equal_to is Not LOGICALLY needed, as you can manually iterate (just use Find()).
1811 * But this CAN be much faster (and commonly is) - and is used very heavily by iterables, so
1812 * its worth the singling out of this important special case.
1813 *
1814 * \pre Common::IEqualToOptimizable<T>; would like to only define (with requires) but
1815 * cannot seem to do in C++20 - requires on virtual function
1816 *
1817 * Default implemented as
1818 * \code
1819 * return Find ([] (const T& lhs) { return equal_to<T>{}(lhs, v); }, seq);
1820 * \endcode
1821 *
1822 * \note An override MUST return the FIRST match in iteration order, unconditionally - there is no
1823 * findFirst argument here because there is no choice to offer. Unlike _IRep::Find (), this is
1824 * called on behalf of callers that need the first (it is how First () reaches an indexed
1825 * backend), and 'equal to v' gives an override nothing cheaper to find than the first anyway:
1826 * the tree backends use lower_bound () precisely to honor this over a run of equal elements
1827 * (see SortedCollection_stdmultiset.inl), and Ensure () against the default implementation.
1828 *
1829 * Note this promises MORE than the PUBLIC Iterable<T>::Find (), which promises only 'a match'.
1830 * That is fine - it is a floor, not a ceiling - and the public looser promise is deliberate.
1831 *
1832 * \note 'seq' here is a pure performance knob, as in std::<execution>: it may change how the search
1833 * runs, never which element comes back.
1834 *
1835 * \see _IRep::MakeIterator for rules about lifetime of returned Iterator<T>
1836 */
1837 virtual Iterator<value_type> Find_equal_to (const ArgByValueType<T>& v, Execution::SequencePolicy seq) const;
1838
1839 public:
1840 /**
1841 * \brief Hand back this backend's elements as one contiguous, in-iteration-order block - or nullopt if it has none.
1842 *
1843 * Lets an algorithm take a bulk-memory fast path (memcpy, std::ranges over a span, ...) instead of
1844 * walking the Iterable one element at a time through virtual calls. That difference is not small:
1845 * measured at ~0.06ns/element to copy an int through a span versus ~11ns/element through
1846 * Iterable<T>'s iterators ('Test52 --show', the As<vector<int>> entry).
1847 *
1848 * Defaults to nullopt, so this is purely additive - a backend that does not override it keeps
1849 * working, just without the fast path. Every caller must therefore have a working slow path.
1850 *
1851 * \note The span is a BORROWED VIEW, not a copy. It is invalidated by the next mutation of this
1852 * rep, and must never outlive the _SafeReadRepAccessor the caller obtained it through.
1853 * Deliberately NOT spelled As<...>, which means "materialize an owning copy you can keep".
1854 *
1855 * \pre Caller holds a _SafeReadRepAccessor (or _SafeReadWriteRepAccessor) on the envelope for as
1856 * long as it uses the result. That accessor holds the envelope's read context for its
1857 * lifetime, so a concurrent mutation through the same envelope is still caught in debug
1858 * builds; one through a DIFFERENT envelope must COW-clone before mutating and so cannot
1859 * touch this buffer. Without that, the span outlives its race detection.
1860 *
1861 * \note Overriders must return elements in ITERATION order. A backend whose storage order differs
1862 * from the order MakeIterator () yields (or which is not contiguous at all) must return
1863 * nullopt - silently returning storage order would corrupt every caller.
1864 *
1865 * \note Overriders must return storage that is WRITABLE when this rep is reached through
1866 * _GetWriteableRep () - ie the span must view the backend's own mutable buffer, never
1867 * genuinely immutable memory (a read-only memory mapping, a shared constant pool, ...).
1868 * The return type is span<const value_type> because reading is all this hook promises;
1869 * but an in-place algorithm that has already established sole ownership through
1870 * _GetWriteableRep () is entitled to const_cast and write through it, and that is the
1871 * intended way to get an in-place fast path WITHOUT adding a second (mutable) virtual
1872 * here. See the design note on Sequence<T>::_IRep for why that matters.
1873 */
1874 virtual optional<span<const value_type>> PeekContiguousStorage () const;
1875 };
1876
1877 /**
1878 * Compare any two iterables as a sequence of elements that can themselves be compared - like strcmp().
1879 * The first pair which is unequally compared - defines the ordering relationship between the two iterables.
1880 * And if one ends before the other, if the LHS ends first, treat that as less (like with alphabetizing) and
1881 * if the right ends first, treat that as >.
1882 *
1883 * SequentialEqualsComparer is commutative().
1884 *
1885 * Computational Complexity: O(N)
1886 */
1887 template <typename T>
1888 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) T_EQUALS_COMPARER>
1889 struct Iterable<T>::SequentialEqualsComparer : Common::ComparisonRelationDeclarationBase<Common::ComparisonRelationType::eEquals> {
1890 constexpr SequentialEqualsComparer (const T_EQUALS_COMPARER& elementComparer = {});
1891 [[deprecated ("Since Stroika v3.0d24 - useIterableSize is ignored; use the CTOR without it")]] constexpr SequentialEqualsComparer (
1892 const T_EQUALS_COMPARER& elementComparer, bool useIterableSize);
1893 nonvirtual bool operator() (const Iterable& lhs, const Iterable& rhs) const;
1894 qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE T_EQUALS_COMPARER fElementComparer;
1895 };
1896
1897 /**
1898 * Compare any two iterables as a sequence of elements that can themselves be compared - like strcmp().
1899 * The first pair which is unequally compared - defines the ordering relationship between the two iterables.
1900 * And if one ends before the other, if the LHS ends first, treat that as less (like with alphabetizing) and
1901 * if the right ends first, treat that as >.
1902 */
1903 template <typename T>
1904 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IThreeWayComparer<T>) T_THREEWAY_COMPARER>
1905 struct Iterable<T>::SequentialThreeWayComparer : Common::ComparisonRelationDeclarationBase<Common::ComparisonRelationType::eThreeWayCompare> {
1906 constexpr SequentialThreeWayComparer (const T_THREEWAY_COMPARER& elementComparer = {});
1907 nonvirtual auto operator() (const Iterable& lhs, const Iterable& rhs) const;
1908 qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE T_THREEWAY_COMPARER fElementComparer;
1909 };
1910
1911#if !qCompilerAndStdLib_constructible_Buggy
1912 // see Satisfies Concepts
1913 // @todo would be nice to include these tests generically as part of template declaration, but cannot figure out how
1914 // to get that working (probably due to when incomplete types evaluated) --LGP 2024-08-21
1915 static_assert (copyable<Iterable<int>>);
1916#endif
1917
1918}
1919
1920/*
1921 ********************************************************************************
1922 ******************************* Implementation Details *************************
1923 ********************************************************************************
1924 */
1925#include "Iterable.inl"
1926
1927#endif /*_Stroika_Foundation_Traversal_Iterable_h_ */
#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
[[msvc::no_unique_address]] isn't always broken in MSVC. Annotate with this on things where its not b...
Definition StdCompat.h:443
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...
shared_lock< const AssertExternallySynchronizedChecker > ReadContext
Instantiate AssertExternallySynchronizedChecker::ReadContext to designate an area of code where prote...
SharedByValue is a utility class to implement Copy-On-Write (aka COW) - sort of halfway between uniqu...
Implementation detail for iterator implementors.
Definition Iterable.h:1743
virtual Iterator< value_type > MakeIterator() const =0
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:238
nonvirtual RESULT_T Join(const CONVERT_TO_RESULT &convertToResult=kDefaultToStringConverter<>, const COMBINER &combiner=Characters::kDefaultStringCombiner) const
ape the JavaScript/python 'join' function - take the parts of 'this' iterable and combine them into a...
nonvirtual RESULT_TYPE MaxValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual Iterable< T > Slice(size_t from, size_t to) const
Definition Iterable.inl:822
static bool SetEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
Definition Iterable.inl:360
nonvirtual bool Any() const
Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any va...
nonvirtual optional< T > Max() const
nonvirtual RESULT_TYPE MedianValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual optional< RESULT_TYPE > Mean() const
nonvirtual Iterator< T > Find(THAT_FUNCTION &&that) const
Run the argument bool-returning function (or lambda) on the elements of the container,...
nonvirtual size_t length() const
STL-ish alias for size() - really in STL only used in string, I think, but still makes sense as an al...
nonvirtual CONTAINER_OF_T As(CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
nonvirtual Iterable< T > Distinct(EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
functional API which iterates over all members of an Iterable, applies a map function to each element...
nonvirtual size_t Count() const
with no args, same as size, with function filter arg, returns number of items that pass.
nonvirtual bool IsOrderedBy(INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
nonvirtual Iterable< T > Repeat(size_t count) const
nonvirtual optional< T > First() const
return first element in iterable, or if 'that' specified, first where 'that' is true,...
Definition Iterable.inl:996
T value_type
value_type is an alias for the type iterated over - like vector<T>::value_type
Definition Iterable.h:251
nonvirtual RESULT_TYPE MinValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual bool All(const function< bool(ArgByValueType< T >)> &testEachElt) const
return true iff argument predicate returns true for each element of the iterable
nonvirtual bool Contains(ArgByValueType< T > element, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
nonvirtual optional< T > Min() const
nonvirtual T NthValue(ptrdiff_t n, ArgByValueType< T > defaultValue={}) const
Find the Nth element of the Iterable<>, but allow for n to be out of range, and just return argument ...
nonvirtual size_t size() const
Returns the number of items contained.
Definition Iterable.inl:311
Iterable(const shared_ptr< _IRep > &rep) noexcept
Iterable's are typically constructed as concrete subtype objects, whose CTOR passed in a shared copya...
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
produce a subset of this iterable where argument function returns true
nonvirtual void Apply(const function< void(ArgByValueType< T > item)> &doToElement) const
Run the argument function (or lambda) on each element of the container.
nonvirtual T Nth(ptrdiff_t n) const
Find the Nth element of the Iterable<>
nonvirtual Iterable< T > Take(size_t nItems) const
Definition Iterable.inl:799
nonvirtual RESULT_TYPE MeanValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual optional< RESULT_TYPE > Median(const INORDER_COMPARE_FUNCTION &compare={}) const
nonvirtual Iterable< T > Skip(size_t nItems) const
Definition Iterable.inl:776
nonvirtual RESULT_TYPE SumValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
static const function< RESULT_T(T)> kDefaultToStringConverter
Definition Iterable.h:1011
nonvirtual optional< REDUCED_TYPE > Reduce(const function< REDUCED_TYPE(ArgByValueType< T >, ArgByValueType< T >)> &op) const
Walk the entire list of items, and use the argument 'op' to combine (reduce) items to a resulting sin...
nonvirtual Iterator< T > begin() const
Support for ranged for, and STL syntax in general.
nonvirtual optional< T > Top() const
return the top/largest value (or the top N values) from this Iterable<T>
Definition Iterable.inl:898
Iterable(const Iterable &) noexcept=default
Iterable are safely copyable (by value). Since Iterable uses COW, this just copies the underlying poi...
nonvirtual optional< RESULT_TYPE > Sum() const
nonvirtual Memory::SharedByValueSupport::SharingState _GetSharingState() const
Definition Iterable.inl:300
static bool SequentialEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
Definition Iterable.inl:436
nonvirtual bool empty() const
Returns true iff size() == 0.
Definition Iterable.inl:317
nonvirtual T LastValue(ArgByValueType< T > defaultValue={}) const
static bool MultiSetEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
Definition Iterable.inl:401
nonvirtual optional< T > Last() const
return last element in iterable, or if 'that' specified, last where 'that' is true,...
nonvirtual T FirstValue(ArgByValueType< T > defaultValue={}) const
return first element in iterable provided default
Iterable(Iterable &&) noexcept=default
Iterable are safely moveable.
static constexpr default_sentinel_t end() noexcept
Support for ranged for, and STL syntax in general.
nonvirtual REDUCED_TYPE ReduceValue(const function< REDUCED_TYPE(ArgByValueType< T >, ArgByValueType< T >)> &op, ArgByValueType< REDUCED_TYPE > defaultValue={}) const
nonvirtual Iterable< T > OrderBy(INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
nonvirtual Iterator< T > MakeIterator() const
Create an iterator object which can be used to traverse the 'Iterable'.
Definition Iterable.inl:305
An Iterator<T> is a copyable object which allows traversing the contents of some container.
Definition Iterator.h:253
String UnoverloadedToString(const T &t)
same as ToString()/1 - but without the potentially confusing multi-arg overloads (confused some templ...
Definition ToString.inl:476
const function< String(String, String, bool)> kDefaultStringCombiner
Definition String.inl:1321
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:36
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...
function object whose action is to map its argument, back to the same value it started with (identity...