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