Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Iterable.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Traversal_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 <vector>
14
15#include "Stroika/Foundation/Common/Common.h"
17#include "Stroika/Foundation/Common/Concepts.h"
21#include "Stroika/Foundation/Execution/Common.h"
25
26/**
27 * \file
28 *
29 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
30 *
31 * TODO:
32 * @todo For methods similar to Iterable<T>::Where() (did for where),
33 * consider a TEMPLATED PARAMETER for the resulting Container type, so you can create a "Set" or whatever by doing
34 * Where... But tricky to uniformly add to different container types. Maybe only ones you can say add, or the adder is
35 * a template paraM?
36 * Eg. Distinct, Take, Skip (maybe those sense logically to be transform operations - so maybe OK now doing others but review
37 * each to see where it makes sense).
38 *
39 * @todo SUBCLASSES of Iterable<> need to overload/replace several of these functions taking
40 * into account (by default) their comparers... Eg. Set<> should overload Distinct to do nothing by
41 * default.
42 *
43 * @todo max should take lambda that folds in the select,
44 * and Distinct and take lambda
45 *
46 * @todo Document (which -not all) Linq-like functions only pull as needed from the
47 * original source, and which force a pull (like where doesn't but max does).
48 *
49 * @todo Consider having Linq-like functions do DELAYED EVALUATION, so the computation only
50 * happens when you iterate. Maybe to some degree this already happens, but could do
51 * more (as MSFT does).
52 *
53 * @todo Ordering of parameters to SetEquals() etc templates? Type deduction versus
54 * default parameter?
55 *
56 * @todo REDO DOCS FOR ITERABLE - SO CLEAR ITS ALSO THE BASIS OF "GENERATORS". IT COULD BE RENAMED
57 * GENERATOR (though don't)
58 */
59
61 class String;
62 extern const function<String (String, String, bool)> kDefaultStringCombiner;
63 template <typename T>
64 String UnoverloadedToString (const T& t);
65}
66
67namespace Stroika::Foundation::Traversal {
68
70 using Common::IEqualsComparer;
71 using Common::IThreeWayComparer;
72
73 /**
74 * IIterable concept: std::ranges::range and iterated over values satisfy argument predicate (if given)
75 *
76 * Checks if argument is ranges::range and if the value of items iterated over ITEM_PREDICATE.
77 *
78 * https://stackoverflow.com/questions/76532448/combining-concepts-in-c-via-parameter
79 */
80 template <typename ITERABLE, template <typename> typename ITEM_PREDICATE = Common::True>
81 concept IIterable = ranges::range<ITERABLE> and ITEM_PREDICATE<ranges::range_value_t<ITERABLE>>::value;
82
83 /**
84 * IIterableOfTo concept: IIterable with the constraint that the items produced by iteration are 'ConvertibleTo' the argument OF_T type
85 *
86 * Checks if argument is ranges::range and if the value of items iterated over is convertible to OF_T.
87 *
88 * \par Example Usage
89 * \code
90 * template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
91 * void Add (ITERABLE_OF_ADDABLE&& addAll);
92 * \endcode
93 */
94 template <typename ITERABLE, typename OF_T>
96 static_assert (IIterableOfTo<vector<int>, int>);
97 static_assert (IIterableOfTo<vector<long int>, int>);
98 static_assert (IIterableOfTo<vector<int>, long int>);
99 static_assert (not IIterableOfTo<vector<string>, int>);
100
101 /**
102 * IIterableOfFrom concept: IIterable with the constraint that the items produced by iteration are 'ConvertibleFrom' the argument OF_T type
103 *
104 * Checks if argument is ranges::range and if the value of items iterated over is convertible to OF_T.
105 */
106 template <typename ITERABLE, typename OF_T>
108 static_assert (IIterableOfFrom<vector<int>, int>);
109 static_assert (IIterableOfFrom<vector<long int>, int>);
110 static_assert (IIterableOfFrom<vector<int>, long int>);
111 static_assert (not IIterableOfFrom<vector<string>, int>);
112
113#if qCompilerAndStdLib_lambdas_in_unevaluatedContext_warning_Buggy
114 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wsubobject-linkage\"")
115#endif
116
117 /**
118 * \brief Iterable<T> is a base class for containers which easily produce an Iterator<T>
119 * to traverse them.
120 *
121 * The Stroika iterators can be used either directly (similar to std::range), or in the STL begin/end style -
122 * and this class supports both styles of usage.
123 *
124 * Iterable<T> also supports read-only applicative operations on the contained data.
125 *
126 * Iterable<T> is much like idea of 'abstract readonly container', but which only supports an
127 * exceedingly simplistic pattern of access.
128 *
129 * \note Satisfies Concepts:
130 * o static_assert (copyable<Iterable<T>>); // not not default-unitarizable, and not equals_comparable
131 *
132 * *Important Design Note* (lifetime of iterators):
133 * The Lifetime of Iterator<T> objects created by an Iterable<T> instance must always be less
134 * than the creating Iterable's lifetime.
135 *
136 * This may not be enforced by implementations (but generally will be in debug builds). But
137 * it is a rule!
138 *
139 * The reason for this is that the underlying memory referenced by the iterator may be going away.
140 * We could avoid this by adding a shared_ptr<> reference count into each iterator, but that
141 * would make iterator objects significantly more expensive, and with little apparent value added.
142 * Similarly for weak_ptr<> references.
143 *
144 * *Important Design Note* (construct with rep, no setrep):
145 * We have no:
146 * nonvirtual void _SetRep (IterableRepSharedPtr rep);
147 *
148 * because allowing a _SetRep() method would complicate the efforts of subclasses of Iterable<T>
149 * to assure that the underlying type is of the appropriate subtype.
150 *
151 * For example - see Bag_Array<T>::GetRep_().
152 *
153 * Note - instead - you can 'assign' (operator=) to replace the value (and dynamic type) of
154 * an Iterable<> (or subclass) instance.
155 *
156 * *Important Design Note* (copy on write/COW):
157 * Iterable uses 'SharedByValue', so that subclasses of Iterable (especially containers) CAN implement
158 * Copy-On-Write (COW). However, not ALL Iterables implement COW. In fact, not all Iterables are mutable!
159 *
160 * Iterable's data can come from arbitrary, programmatic sources (like a sequence of uncomputed random numbers).
161 * 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,
162 * consider using Collection<T> or Sequence<> which is almost the same, but will make a copy of the data, and not allow it to
163 * change without preserve COW semantics.
164 *
165 * *Design Note*:
166 * Why does Iterable<T> contain a size () method?
167 *
168 * o It’s always well defined what size() means (what you would get if you called
169 * MakeIterable() and iterated a bunch of times til the end).
170 *
171 * o Its almost always (and trivial) to perform that computation more efficiently than the
172 * iterate over each element approach.
173 *
174 * The gist of these two consideration means that if you need to find the length of
175 * an Iterable<T>, if it was defined as a method, you can access the trivial implementation,
176 * and if it was not defined, you would be forced into the costly implementation.
177 *
178 * Adding size () adds no conceptual cost – because its already so well and clearly defined
179 * in terms of its basic operation (iteration). And it provides value (maybe just modest value).
180 *
181 * *Design Note*:
182 * Order of Iteration.
183 *
184 * Iterables<T> provide no promises about the order of iteration. Specific subclasses (like SortedSet<>)
185 * often will make specific guarantees about order of iteration.
186 *
187 * We do NOT even promise you will see the same items, or seem them in the same order as you iterate
188 * (so for example, you can have a "RandomSequence<>" subclass from Iterable<> and return a different
189 * sequence of numbers each time you make an iterate and run.
190 *
191 * *Design Note*:
192 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
193 * Chose NOT to include an equal_to<Iterable<T>> partial specialization here, but instead duplicatively in
194 * each subclass, so that it could more easily be implemented efficiently (not a biggie), but more
195 * importantly because it doesn't appear to me to make sense so say that a Stack<T> == Set<T>, even if
196 * their values were the same. In other words, the meaning of 'equals' varies between different kinds of
197 * iterables (over the same type).
198 *
199 * We DO have methods SetEquals/MultiSetEquals/SequentialEquals (see below), as well as SequentialThreeWayComparer<> etc.
200 *
201 * \em Design Note
202 * Methods like Min/Max/Median/Sum make little sense on empty Iterables. There were several choices
203 * available to deal with this:
204 * > Assertion
205 * > throw range_error()
206 * > return a sensible default value (e.g. 0) for empty lists
207 * > overloads to let callers select the desired behavior
208 *
209 * Because I wanted these methods to be useful in scenarios like with database queries (inspired by Linq/ORMs)
210 * assertions seemed a poor choice.
211 *
212 * throw range_error makes sense, but then requires lots of checking when used for throws, and that makes use needlessly complex.
213 *
214 * So we eventually decided to use the return optional and have a variant named XXXValue () that returns the plain T with a default - since
215 * we use that pattern in so many places.
216 *
217 * *Design Note* - Microsoft Linq:
218 * This API implements some of the Microsoft Linq API.
219 * https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods(v=vs.100).aspx
220 *
221 * For example, we implement:
222 * o Map **most important**
223 * o Reduce **important - aka accumulate**
224 * o Where
225 * o Take
226 * o Skip
227 * o OrderBy
228 * o First/Last/FirstValue/LastValue (though semantics and later names differ somewhat from .net FirstOrDefault)
229 *
230 * We choose explicitly not to implement
231 * o ToList/ToArray, no need because we have As<>, plus no List/Array classes (exactly).
232 *
233 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
234 *
235 */
236 template <typename T>
237 class Iterable {
238 // requirements about properties of 'T' which logically should have been template type constraints, but wasn't able to get
239 // that working
240 public:
241 static_assert (copy_constructible<Iterator<T>>, "Must be able to create Iterator<T> to use Iterable<T>");
242 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...
243
244 public:
245 /**
246 * \brief value_type is an alias for the type iterated over - like vector<T>::value_type
247 */
248 using value_type = T;
249
250 public:
251 /**
252 * For Stroika containers, all iterators are really const_iterators, but this allows for better STL interoperability.
253 */
255
256 public:
257 /**
258 * For better STL interoperability.
259 */
261
262 protected:
263 class _IRep;
264
265 public:
266 /**
267 * \brief Iterable are safely copyable (by value). Since Iterable uses COW, this just copies the underlying pointer and increments the reference count.
268 */
269 Iterable (const Iterable&) noexcept = default;
270
271 public:
272 /**
273 * \brief Iterable are safely moveable.
274 */
275 Iterable (Iterable&&) noexcept = default;
276
277 public:
278 /**
279 * Make a copy of the given argument, and treat it as an iterable.
280 *
281 * \par Example Usage
282 * \code
283 * Iterable<int> aa6{3, 4, 6};
284 * \endcode
285 *
286 * \note Don't apply this constructor to non-containers (non-iterables),
287 * and don't allow it to apply to SUBCLASSES of Iterable (since then we want to select the Iterable (const Iterable& from) constructor)
288 */
289 template <IIterableOfTo<T> CONTAINER_OF_T>
290 explicit Iterable (CONTAINER_OF_T&& from)
291 requires (not derived_from<remove_cvref_t<CONTAINER_OF_T>, Iterable<T>>)
292#if qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
293 : _fRep{mk_ (forward<CONTAINER_OF_T> (from))._fRep} {}
294#endif
295 ;
296
297 public:
298 /**
299 * \note Use of initializer_list<T> (@see http://stroika-bugs.sophists.com/browse/STK-739)
300 * Because of quirks of C++ overload resolution (https://en.cppreference.com/w/cpp/language/list_initialization)
301 * use of mem-initializers with Iterable<T> constructor calls have the unintuitive behavior of
302 * invoking the initializer_list<T> constructor preferentially (see docs above and 'Otherwise, the constructors of T are considered, in two phases'
303 */
304 Iterable (const initializer_list<T>& from);
305
306 protected:
307 /**
308 * \brief Iterable's are typically constructed as concrete subtype objects,
309 * whose CTOR passed in a shared copyable rep.
310 *
311 * \note - the repPtr in construction can be, so that we don't
312 * need to increment its reference count as we pass it though the call chain to where it will be finally
313 * stored.
314 */
315 explicit Iterable (const shared_ptr<_IRep>& rep) noexcept;
316 explicit Iterable (shared_ptr<_IRep>&& rep) noexcept;
317
318 public:
319 ~Iterable () = default;
320
321 public:
322 /**
323 */
324 nonvirtual Iterable& operator= (Iterable&& rhs) noexcept = default;
325 nonvirtual Iterable& operator= (const Iterable& rhs) noexcept = default;
326
327 public:
328 /**
329 * Often handy short-hand (punning) for a container to see if zero elts, then if on it returns false.
330 */
331 nonvirtual explicit operator bool () const;
332
333 public:
334 /**
335 * \brief Create an iterator object which can be used to traverse the 'Iterable'.
336 *
337 * Create an iterator object which can be used to traverse the 'Iterable' - this object -
338 * and visit each element.
339 *
340 * \note LIFETIME NOTE:
341 * Iterators created this way, become invalidated (generally detected in debug builds), and cannot be used
342 * after the underlying Iterable is modified.
343 */
344 nonvirtual Iterator<T> MakeIterator () const;
345
346 public:
347 /**
348 * \brief Returns the number of items contained.
349 *
350 * size () returns the number of elements in this 'Iterable' object. Its defined to be
351 * the same number of elements you would visit if you created an iterator (MakeIterator())
352 * and visited all items. In practice, as the actual number might vary as the underlying
353 * iterable could change while being iterated over.
354 *
355 * For example, a filesystem directory iterable could return a different length each time it was
356 * called, as files are added and removed from the filesystem.
357 *
358 * Also note that size () can return a ridiculous number - like numeric_limits<size_t>::max () -
359 * for logically infinite sequences... like a sequence of random numbers.
360 *
361 * @aliases GetLength () - in fact in Stroika before 2.1b14, this was called GetLength ()
362 *
363 * \note Design Note: noexcept
364 * We chose to allow the empty () method to allow exceptions, since an Iterable<T>
365 * is general enough (say externally network data sourced) - it could be temporarily or otherwise unavailable.
366 *
367 * \em Performance:
368 * The performance of size() may vary wildly. It could be anywhere from O(1) to O(N)
369 * depending on the underlying type of Iterable<T>.
370 */
371 nonvirtual size_t size () const;
372
373 public:
374 /**
375 * \brief Returns true iff size() == 0
376 *
377 * @aliases IsEmpty () - called IsEmpty () in Stroika 2.1b13 and prior
378 *
379 * \note Design Note: noexcept
380 * We chose to allow the empty () method to allow exceptions, since an Iterable<T>
381 * is general enough (say externally network data sourced) - it could be temporarily or otherwise unavailable.
382 *
383 * \note Runtime performance/complexity:
384 * The performance of empty() may vary wildly (@see size) but will nearly always be constant complexity.
385 */
386 nonvirtual bool empty () const;
387
388 public:
389 /**
390 * Apply the (template argument) EQUALS_COMPARER to each element in the Iterable<T> and
391 * return true iff found. This invokes no virtual methods dependent (except MakeIterable or some such)
392 * and so gains no performance benefits from the organization of the underlying Iterable<T>. This
393 * is just a short hand for the direct iteration one would trivially code by hand. Still - its
394 * easier to call Contains() that to code that loop!
395 *
396 * And note - subclasses (like Containers::Set<T>) will hide this implementation with a more
397 * efficient one (that does indirect to the backend).
398 *
399 * \em Performance:
400 * This algorithm is O(N).
401 *
402 */
403 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
404 nonvirtual bool Contains (ArgByValueType<T> element, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
405
406 public:
407 /**
408 * SetEquals () - very inefficiently - but with constant small memory overhead - returns true if
409 * each element in the each iterable is contained in the other. The lengths CAN be different
410 * and the two Iterables<> be SetEquals().
411 *
412 * \em Performance:
413 * This algorithm is O(N) * O(M) where N and M are the length of the two respective iterables.
414 *
415 * \note \todo - consider alternative implementation where we accumulate into std::set<>.
416 * Assume without loss of generality that N is the smaller side (can be determined in O(M)).
417 * Accumulate into set would take N*log (N).
418 * Then we would iterate over M (O(M)), and each time check log(N)). So time would be sum of
419 * N*log (N) + M*(log(N)) or (N + M)*log(N).
420 * That's a little better (but at the cost of more RAM usage).
421 * NOTE ALSO - that 'trick' assumes T has a valid less<T>, which it may not!
422 *
423 */
424 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
425 static bool SetEquals (const LHS_CONTAINER_TYPE& lhs, const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{});
426 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
427 nonvirtual bool SetEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
428
429 public:
430 /**
431 * MultiSetEquals () - very inefficiently - but with constant small memory overhead - returns true if
432 * each element in the each iterable is contained in the other. They lengths CAN be different
433 * and the two Iterables<> be SetEquals().
434 *
435 * \em Performance:
436 * This algorithm is O(N^^3)
437 */
438 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
439 static bool MultiSetEquals (const LHS_CONTAINER_TYPE& lhs, const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{});
440 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
441 nonvirtual bool MultiSetEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
442
443 public:
444 /**
445 * SequentialEquals () - measures if iteration over the two containers produces identical sequences
446 * of elements (identical by compare with EQUALS_COMPARER). It does not call 'size' - by default - but just iterates (unless the paraemter useIterableSize)
447 *
448 * \note - RHS_CONTAINER_TYPE can be any iterable, including an STL container like vector or initializer_list
449 *
450 * \note If useIterableSize == true (Defaults false), size() method must be quick, and unchanged during the lifetime of the the comparison.
451 *
452 * \em Performance:
453 * This algorithm is O(N)
454 */
455 template <ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
456 static bool SequentialEquals (const LHS_CONTAINER_TYPE& lhs, const RHS_CONTAINER_TYPE& rhs,
457 EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}, bool useIterableSize = false);
458 template <ranges::range RHS_CONTAINER_TYPE = initializer_list<T>, IEqualsComparer<T> EQUALS_COMPARER = equal_to<T>>
459 nonvirtual bool SequentialEquals (const RHS_CONTAINER_TYPE& rhs, EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{},
460 bool useIterableSize = false) const;
461
462 public:
463 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) T_EQUALS_COMPARER = equal_to<T>>
464 struct SequentialEqualsComparer;
465
466 public:
467 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IThreeWayComparer<T>) T_THREEWAY_COMPARER = compare_three_way>
468 struct SequentialThreeWayComparer;
469
470 public:
471 /**
472 * \brief Support for ranged for, and STL syntax in general
473 *
474 * begin ()/end() are similar to MakeIterator(), except that they allow for iterators to be
475 * used in an STL-style, which is critical for using C++ ranged iteration.
476 *
477 * \par Example Usage
478 * \code
479 * for (Iterator<T> i = c.begin (); i != c.end (); ++i) {
480 * if (*i = T{}) {
481 * break;
482 * }
483 * }
484 * \endcode
485 *
486 * OR
487 * \code
488 * for (const T& i : c) {
489 * if (*i = T{}) {
490 * break;
491 * }
492 * }
493 * \endcode
494 *
495 */
496 nonvirtual Iterator<T> begin () const;
497
498 public:
499 /**
500 * \brief Support for ranged for, and STL syntax in general
501 *
502 * \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).
503 * \note in Stroika v3.0d10 - changed return type to default_sentinel_t (from Iterator<T>).
504 */
505 static constexpr default_sentinel_t end () noexcept;
506
507 public:
508 /**
509 * \brief Run the argument function (or lambda) on each element of the container.
510 *
511 * Take the given function argument, and call it for each element of the container. This
512 * is equivalent to:
513 *
514 * for (Iterator<T> i = begin (); i != end (); ++i) {
515 * (doToElement) (*i);
516 * }
517 *
518 * However, Apply () MAY perform the entire iteration more quickly (depending on the
519 * kind of the container).
520 *
521 * Apply () also MAY be much faster than normal iteration (some simple tests
522 * - around 2015-02-15 - suggest Apply () is perhaps 10x faster than using an iterator).
523 *
524 * \par Example Usage
525 * \code
526 * unsigned int cnt { 0 };
527 * s.Apply ([&cnt] (int i) {
528 * cnt += i;
529 * });
530 * DbgTrace ("cnt={}"_f, cnt);
531 * \endcode
532 *
533 * \note on 'seq' parameter, if you pass anything but (the default) eSeq value, be sure to check
534 * function argument is threadsafe.
535 *
536 * \note Aliases:
537 * o Apply could have logically been called ForEach, and is nearly identical to
538 * std::for_each (), except for not taking iterators as arguments, and not having
539 * any return value.
540 *
541 * \note Why Apply takes std::function argument instead of templated FUNCTION parameter?
542 * Because Stroika iterables use a 'virtual' APPLY, you cannot pass arbitrary templated
543 * function calls passed that boundary. That choice ALLOWS traversal to be implemented
544 * quickly, and without and subsequent (virtual) calls on the container side, but one
545 * - CALL per iteration to the function itself.
546 *
547 * \note \em Thread-Safety The argument function (lambda) may
548 * directly (or indirectly) access the Iterable<> being iterated over.
549 */
550 nonvirtual void Apply (const function<void (ArgByValueType<T> item)>& doToElement,
551 Execution::SequencePolicy seq = Execution::SequencePolicy::eDEFAULT) const;
552
553 public:
554 /**
555 * \brief Run the argument bool-returning function (or lambda) on each element of the
556 * container, and return an iterator pointing at the first element (depending on seq) found true.
557 * (or use First() to do same thing but return optional<>)
558 *
559 * Take the given function argument, and call it for each element of the container. This is
560 * equivalent to:
561 *
562 * for (Iterator<T> i = begin (); i != end (); ++i) {
563 * if (that (*i)) {
564 * return it;
565 * }
566 * }
567 * return end();
568 *
569 * This function returns an iterator pointing to the element that triggered the abrupt loop
570 * end (for example the element you were searching for?). It returns the special iterator
571 * end() to indicate no doToElement() functions returned true.
572 *
573 * Also, note that this function does NOT change any elements of the Iterable.
574 *
575 * \note about seq - eSeq - then the item returned will be first in
576 * iteration order. But if you pass in some other Execution::SequencePolicy 'seq', the algorithm
577 * will return the 'first it finds'.
578 *
579 * If you really care that the result is first, probably better to call Iterable<>::First (). Though
580 * it amounts to the same thing (setting SequencePolicy::eSeq) - its better documenting.
581 *
582 * Note that this used to be called 'ContainsWith' - because it can act the same way (due to
583 * operator bool () method of Iterator<T>).
584 *
585 * \note This is much like First(), except that it optional takes a different starting point, and
586 * it returns an Iterator<T> instead of an optional<T>
587 * First () - often more handy.
588 *
589 * \note though semantically similar to iterating, it maybe faster, due to delegating 'search' to backend container
590 * implementation (though then call to lambda/checker maybe indirected countering this performance benefit).
591 *
592 * @aliases FirstThat
593 *
594 * @see Apply
595 *
596 * \note \em Thread-Safety The argument function (lambda) may
597 * directly (or indirectly) access the Iterable<> being iterated over.
598 *
599 * \par Example Usage
600 * \code
601 * bool IsAllWhitespace (String s) const
602 * {
603 * return not s.Find ([] (Character c) -> bool { return not c.IsWhitespace (); });
604 * }
605 * \endcode
606 *
607 * \see See Also First (f) - if you just want the first one...
608 *
609 * \note - because the lifetime of the iterable must exceed that of the iterator, its generally unsafe to use Find()
610 * on a temporary (except with the trick if (auto i = x().Find(...)) { ok to access i here cuz x() temporary
611 * not destroyed yet).
612 *
613 * \note despite the name EQUALS_COMPARER, we allow EQUALS_COMPARER to just be IPotentiallyComparer<> and don't require
614 * EqualsComparer, just to simplify use, and because we cannot anticipate any real ambiguity or confusion resulting from this loose restriction.
615 */
616 template <predicate<T> THAT_FUNCTION>
617 nonvirtual Iterator<T> Find (THAT_FUNCTION&& that, Execution::SequencePolicy seq = Execution::SequencePolicy::eDEFAULT) const;
618 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER>
619 nonvirtual Iterator<T> Find (Common::ArgByValueType<T> v, EQUALS_COMPARER&& equalsComparer = {},
620 Execution::SequencePolicy seq = Execution::SequencePolicy::eDEFAULT) const;
621 template <predicate<T> THAT_FUNCTION>
622 nonvirtual Iterator<T> Find (const Iterator<T>& startAt, THAT_FUNCTION&& that,
623 Execution::SequencePolicy seq = Execution::SequencePolicy::eDEFAULT) const;
624 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER>
625 nonvirtual Iterator<T> Find (const Iterator<T>& startAt, Common::ArgByValueType<T> v, EQUALS_COMPARER&& equalsComparer = {},
626 Execution::SequencePolicy seq = Execution::SequencePolicy::eDEFAULT) const;
627
628 public:
629 /**
630 * As<CONTAINER_OF_T> () can be used to easily map an iterable to another container
631 * (for example STL container) which supports begin/end iterator constructor. This is
632 * really just a shorthand for
633 * CONTAINER_OF_T{this->begin (), this->end ()};
634 *
635 * Note - this also works with (nearly all) of the Stroika containers as well
636 * (e.g. Set<T> x; x.As<Sequence<T>> ());
637 *
638 * \em Design Note:
639 * We chose NOT to include an overload taking iterators because there was no connection between
640 * 'this' and the used iterators, so you may as well just directly call CONTAINER_OF_T{it1, it2}.
641 */
642 template <IIterableOfFrom<T> CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
643 nonvirtual CONTAINER_OF_T As (CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const;
644
645 public:
646 /**
647 * \brief Find the Nth element of the Iterable<>
648 *
649 * if n < 0, treated as from the end, so actual index = size () + n
650 *
651 * \par Example Usage
652 * \code
653 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
654 * EXPECT_EQ (c.Nth (1), 2);
655 * EXPECT_EQ (c.Nth (-1), 6);
656 * \endcode
657 *
658 * \pre n < size () // for size_t overload
659 * \pre n < size () and n > -size() // for ptrdiff_t overload
660 */
661 nonvirtual T Nth (ptrdiff_t n) const;
662
663 public:
664 /**
665 * \brief Find the Nth element of the Iterable<>, but allow for n to be out of range, and just return argument default-value
666 *
667 * \par Example Usage
668 * \code
669 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
670 * EXPECT_EQ (c.NthValue (1), 2);
671 * EXPECT_EQ (c.NthValue (99), int{});
672 * \endcode
673 *
674 */
675 nonvirtual T NthValue (ptrdiff_t n, ArgByValueType<T> defaultValue = {}) const;
676
677 public:
678 /**
679 * \brief produce a subset of this iterable where argument function returns true
680 *
681 * BASED ON Microsoft .net Linq.
682 *
683 * @aliases Filter
684 * @aliases AllThat, AllOf
685 *
686 * This returns either an Iterable<T>, or a concrete container (provided template argument). If returning
687 * just an Iterable<T>, then the result is lazy evaluated. If a concrete container is provided, its fully constructed
688 * when Where returns.
689 *
690 * \par Example Usage
691 * \code
692 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
693 * EXPECT_TRUE (c.Where ([] (int i) { return i % 2 == 0; }).SequentialEquals (Iterable<int> { 2, 4, 6 }));
694 * \endcode
695 *
696 * \note Could have been called EachWith, EachWhere, EachThat (), AllThat, AllWhere, Filter, or SubsetWhere.
697 *
698 * \note This is NEARLY IDENTICAL to the Map<RESULT_CONTAINER> function - where it uses its optional returning filter function.
699 * Please where cannot be used to transform the shape of the data (e.g. projections) whereas Map() can.
700 * But for the filter use case, this is a bit terser, so maybe still useful --LGP 2022-11-15
701 *
702 * \see See also Map<RESULT_CONTAINER,ELEMENT_MAPPER> ()
703 */
704#if qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
705 template <typename RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
706 nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE&& includeIfTrue) const;
707 template <typename RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
708 nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE&& includeIfTrue, RESULT_CONTAINER&& emptyResult) const;
709#else
710 template <derived_from<Iterable<T>> RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
711 nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE&& includeIfTrue) const;
712 template <derived_from<Iterable<T>> RESULT_CONTAINER = Iterable<T>, predicate<T> INCLUDE_PREDICATE>
713 nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE&& includeIfTrue, RESULT_CONTAINER&& emptyResult) const;
714#endif
715
716 public:
717 /**
718 * BASED ON Microsoft .net Linq.
719 *
720 * This returns an Iterable<T> that contains just the subset of the items which are distinct (equality comparer)
721 *
722 * \par Example Usage
723 * \code
724 * Iterable<int> c { 1, 2, 2, 5, 9, 4, 5, 6 };
725 * EXPECT_TRUE (c.Distinct ().SetEquals (Iterable<int> { 1, 2, 4, 5, 6, 9 }));
726 * \endcode
727 *
728 * @todo need overloads taking lambda that projects
729 * @todo for now use builtin stl set to accumulate, but need flexibility on where compare and maybe also redo with hash?
730 */
731 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<T>>
732 nonvirtual Iterable<T> Distinct (EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
733 template <typename RESULT, Common::IPotentiallyComparer<T> EQUALS_COMPARER = equal_to<RESULT>>
734 nonvirtual Iterable<RESULT> Distinct (const function<RESULT (ArgByValueType<T>)>& extractElt,
735 EQUALS_COMPARER&& equalsComparer = EQUALS_COMPARER{}) const;
736
737 public:
738 /**
739 * \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
740 *
741 * This is like the map() function in so many other languages, like lisp, JavaScript, etc, **not** like the STL::map class.
742 *
743 * The transformation may be a projection, or complete transformation. If the 'extract' function returns optional<RESULT_COLLECTION::value_type>, then a missing
744 * value is treated as removal from the source list (in the resulting generated list).
745 *
746 * \note - @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
747 * as it does essentially the same thing. It can be used to completely transform a container of one thing
748 * into a (possibly smaller) container of something else by iterating over all the members, applying a function, and
749 * (optionally) appending the result of that function to the new container.
750 *
751 * \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.
752 * But since that release, we just take the second parameter (as first) - and infer the RESULT_ELELMENT_TYPE.
753 *
754 * \note Prior to Stroika v2.1.10, this was called Select ()
755 *
756 * \note - The overloads returning Iterable<RESULT> do NOT IMMEDIATELY traverse its argument, but uses @see CreateGenerator - to create a new iterable that dynamically pulls
757 * from 'this' Iterable<>'.
758 *
759 * The overloads returning RESULT_CONTAINER DO however immediately construct RESULT_CONTAINER, and fill it in the the result
760 * of traversal before Map () returns.
761 *
762 * \note This can be used to filter data, but if that is the only goal, 'Where' is a better choice. If the argument function
763 * returns optional<THE RETURN TYPE> - then only accumulate those that are returned with has_value () (so also can be used to filter).
764 *
765 * \par Example Usage
766 * \code
767 * Iterable<pair<int,char>> c { {1, 'a'}, {2, 'b'}, {3, 'c'} };
768 * EXPECT_TRUE (c.Map<Iterable<int>> ([] (pair<int,char> p) { return p.first; }).SequentialEquals (Iterable<int> { 1, 2, 3 }));
769 * \endcode
770 *
771 * This can also easily be used to TRANSFORM an iterable.
772 * \par Example Usage
773 * \code
774 * Iterable<int> c { 3, 4, 7 };
775 * EXPECT_TRUE (c.Map<Iterable<String>> ([] (int i) { return Characters::Format ("{}"_f, i); }).SequentialEquals (Iterable<String> { "3", "4", "7" }));
776 * \endcode
777 *
778 * \par Example Usage
779 * or transform into another container type
780 * \code
781 * Iterable<int> c { 3, 4, 7 };
782 * EXPECT_TRUE ((c.Map<vector<String>> ([] (int i) { return Characters::Format ("{}"_f, i); }) == vector<String>{"3", "4", "7"}));
783 * \endcode
784 *
785 * \par Example Usage
786 * \code
787 * void ExpectedMethod (const Request* request, const Set<String>& methods, const optional<String>& fromInMessage)
788 * {
789 * String method{request->GetHTTPMethod ()};
790 * Set<String> lcMethods = methods.Map<Iterable<String>> ([](const String& s) { return s.ToLowerCase (); });
791 * if (not methods.Contains (method.ToLowerCase ())) {
792 * ...
793 * \endcode
794 *
795 * Overload which returns optional<RESULT> and nullopt interpreted as skipping that element
796 *
797 * \par Example Usage
798 * Filtering a list example:
799 * \code
800 * // GetAssociatedContentType -> optional<String> - skip items that are 'missing'
801 * possibleFileSuffixes.Map<Set<InternetMediaType>> ([&] (String suffix) -> optional<InternetMediaType> { return r.GetAssociatedContentType (suffix); })
802 * \endcode
803 *
804 * \note This could have been written as one function/overload, but then for the RESULT_CONTAINER=Iterable<T> case
805 * we would be forced to uselessly create a bogus Iterable, and then throw it away.
806 */
807 template <ranges::range RESULT_CONTAINER = Iterable<T>, invocable<T> ELEMENT_MAPPER>
808 nonvirtual RESULT_CONTAINER Map (ELEMENT_MAPPER&& elementMapper) const
809 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
810 convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>);
811 template <ranges::range RESULT_CONTAINER = Iterable<T>, invocable<T> ELEMENT_MAPPER>
812 nonvirtual RESULT_CONTAINER Map (ELEMENT_MAPPER&& elementMapper, RESULT_CONTAINER&& emptyResult) const
813 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
814 convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>);
815
816 public:
817 /**
818 * \brief Walk the entire list of items, and use the argument 'op' to combine (reduce) items to a resulting single item.
819 *
820 * \see https://en.wikipedia.org/wiki/Reduction_operator
821 * \see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
822 * \see https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?redirectedfrom=MSDN&view=net-7.0#overloads
823 *
824 * @aliases Accumulate
825 *
826 * \note This was called Accumulate in Stroika up until 2.1.10
827 *
828 * \par Example Usage
829 * \code
830 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
831 * EXPECT_TRUE (c.Reduce ([] (T lhs, T rhs) { return lhs + rhs; }) == 24);
832 * \endcode
833 *
834 * \par Implementation As if:
835 * \code
836 * optional<RESULT_TYPE> result;
837 * for (const auto& i : *this) {
838 * if (result) {
839 * result = op (i, *result);
840 * }
841 * else {
842 * result = i;
843 * }
844 * }
845 * \endcode
846 *
847 * \note returns nullopt if empty list
848 *
849 * See:
850 * @see ReduceValue
851 * @see Join
852 * @see Sum
853 * @see SumValue
854 */
855 template <typename REDUCED_TYPE = T>
856 nonvirtual optional<REDUCED_TYPE> Reduce (const function<REDUCED_TYPE (ArgByValueType<T>, ArgByValueType<T>)>& op) const;
857
858 public:
859 /**
860 * @see @Reduce, but if value is missing, returns defaultValue arg or {}
861 */
862 template <typename REDUCED_TYPE = T>
863 nonvirtual REDUCED_TYPE ReduceValue (const function<REDUCED_TYPE (ArgByValueType<T>, ArgByValueType<T>)>& op,
864 ArgByValueType<REDUCED_TYPE> defaultValue = {}) const;
865
866 public:
867 /**
868 * kDefaultToStringConverter encapsulates the algorithm used to map T objects to printable strings. As this is
869 * mainly used for debugging, it defaults to using Characters::ToString() - and so maybe lossy.
870 *
871 * For plain Strings - however, it just uses Common::Identity (no mapping). So that when used in Join - you get
872 * no changes to the argument strings (by default - easy to pass in lambda todo what you want to Join).
873 *
874 * \note - logically - kDefaultToStringConverter takes no template parameter, but in practical use, it must
875 * just to postpone the evaluation of its type argument and avoid a direct dependency on the String module,
876 * which in turn depends on this module.
877 */
878 template <same_as<Characters::String> RESULT_T = Characters::String>
879 static inline const function<RESULT_T (T)> kDefaultToStringConverter = [] () -> function<Characters::String (T)> {
880 if constexpr (same_as<T, Characters::String> and same_as<RESULT_T, Characters::String>) {
881 return Common::Identity{};
882 }
883 else {
884 return Characters::UnoverloadedToString<T>;
885 }
886 }();
887
888 public:
889 /**
890 * \brief ape the JavaScript/python 'join' function - take the parts of 'this' iterable and combine them into a new object (typically a string)
891 *
892 * This Join () API - if you use the template, is fairly generic and lets the caller iterate over subelements of this iterable, and
893 * combine them into a new thing (@see Reduce - it is similar but more general).
894 *
895 * For the very common case of accumulating objects into a String, there are additional (stringish) overloads that more closely mimic
896 * what you can do in JavaScript/python.
897 *
898 * Gist of arguments
899 * o convertToResult: - OPTIONAL converter from T to String
900 * o combiner: - OPTIONAL thing that joins two RESULT_T (result of above covertToResult - typically String)
901 * and combiner MAYBE replaced with String (separator and optionally finalStringSeparator)
902 *
903 * \note The String returning overload converts to String with kDefaultToStringConverter (Characters::ToString - mostly), so this may not be
904 * a suitable conversion in all cases (mostly intended for debugging or quick cheap display)
905 *
906 * \par Example Usage
907 * \code
908 * Iterable<InternetAddress> c{IO::Network::V4::kLocalhost, IO::Network::V4::kAddrAny};
909 * EXPECT_EQ (c.Join (), "localhost, INADDR_ANY");
910 * EXPECT_EQ (c.Join ("; "), "localhost; INADDR_ANY");
911 * \endcode
912 *
913 * \par Example Usage
914 * \code
915 * const Iterable<String> kT1_{"a", "b"};
916 * const Iterable<String> kT2_{"a", "b", "c"};
917 * EXPECT_EQ (kT1_.Join (Characters::UnoverloadedToString<String>), "'a', 'b'");
918 * EXPECT_EQ (kT1_.Join (Iterable<String>::kDefaultToStringConverter<String>), kT1_.Join ());
919 * // Common::Identity{} produces no transformation, and the combiner function just directly concatenates with no separator
920 * EXPECT_EQ (kT1_.Join (Common::Identity{}, [] (auto l, auto r, bool) { return l + r; }), "ab");
921 * EXPECT_EQ (kT1_.Join (), "a, b");
922 * EXPECT_EQ (kT1_.Join (" "), "a b");
923 * EXPECT_EQ (kT1_.Join (", ", " and "), "a and b");
924 * EXPECT_EQ (kT2_.Join (", ", " and "), "a, b and c");
925 * EXPECT_EQ (kT2_.Join ([] (auto i) { return i.ToUpperCase (); }), "A, B, C");
926 * EXPECT_EQ (kT2_.Join ([] (auto i) { return i.ToUpperCase (); }, "; "sv, " and "sv), "A; B and C");
927 * \endcode
928 *
929 * See:
930 * @see Accumulate
931 */
932#if qCompilerAndStdLib_template_SubstDefaultTemplateParamVariableTemplate_Buggy
933 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<RESULT_T>),
934 invocable<RESULT_T, RESULT_T, bool> COMBINER = decltype (Characters::kDefaultStringCombiner)>
935 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult = kDefaultToStringConverter<RESULT_T>,
936 const COMBINER& combiner = Characters::kDefaultStringCombiner) const
937 requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T> and
938 convertible_to<invoke_result_t<COMBINER, RESULT_T, RESULT_T, bool>, RESULT_T>);
939#else
940 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<>),
941 invocable<RESULT_T, RESULT_T, bool> COMBINER = decltype (Characters::kDefaultStringCombiner)>
942 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult = kDefaultToStringConverter<>,
943 const COMBINER& combiner = Characters::kDefaultStringCombiner) const
944 requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T> and
945 convertible_to<invoke_result_t<COMBINER, RESULT_T, RESULT_T, bool>, RESULT_T>);
946#endif
947#if qCompilerAndStdLib_template_optionalDeclareIncompleteType_Buggy
948 nonvirtual Characters::String Join (const Characters::String& separator) const;
949 nonvirtual Characters::String Join (const Characters::String& separator, const optional<Characters::String>& finalSeparator) const;
950 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
951 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult, const RESULT_T& separator) const
952 requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T>);
953 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
954 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult, const RESULT_T& separator, const optional<RESULT_T>& finalSeparator) const
955 requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T>);
956#else
957 nonvirtual Characters::String Join (const Characters::String& separator, const optional<Characters::String>& finalSeparator = {}) const;
958 template <typename RESULT_T = Characters::String, invocable<T> CONVERT_TO_RESULT>
959 nonvirtual RESULT_T Join (const CONVERT_TO_RESULT& convertToResult, const RESULT_T& separator, const optional<RESULT_T>& finalSeparator = {}) const
960 requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T>);
961#endif
962
963 public:
964 /**
965 * BASED ON Microsoft .net Linq.
966 *
967 * This returns an Iterable<T> with a subset of data after skipping the argument number of items.
968 * If the number of items skipped is greater or equal to the length of the original Iterable, then
969 * an empty Iterable is returned.
970 *
971 * \par Example Usage
972 * \code
973 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
974 * EXPECT_TRUE (c.Skip (3).SequentialEquals (Iterable<int> { 4, 5, 6 }));
975 * \endcode
976 *
977 * @see https://msdn.microsoft.com/en-us/library/bb358985%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
978 * @Take
979 */
980 nonvirtual Iterable<T> Skip (size_t nItems) const;
981
982 public:
983 /**
984 * BASED ON Microsoft .net Linq.
985 *
986 * This returns an Iterable<T> with up to nItems taken from the front of this starting iterable. If this Iterable
987 * is shorter, Take () returns just the original Iterable
988 *
989 * \par Example Usage
990 * \code
991 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
992 * EXPECT_TRUE (c.Take (3).SequentialEquals (Iterable<int> { 1, 2, 3 }));
993 * \endcode
994 *
995 * @see https://msdn.microsoft.com/en-us/library/bb503062(v=vs.110).aspx
996 * @Skip
997 */
998 nonvirtual Iterable<T> Take (size_t nItems) const;
999
1000 public:
1001 /**
1002 * This returns an Iterable<T> based on the current iterable, with the subset from position from to to.
1003 * If some items don't exist, the resulting list is shortened (not an assertion error).
1004 * Item at from is included in the output, but item 'to' is not included.
1005 *
1006 * \par Example Usage
1007 * \code
1008 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1009 * EXPECT_TRUE (c.Slice (3, 5).SequentialEquals ({ 4, 5 }));
1010 * \endcode
1011 *
1012 * \pre from <= to
1013 *
1014 * \note equivalent to Skip (from).Take (to-from)
1015 *
1016 * @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?)
1017 * @see Take
1018 * @see Slice
1019 */
1020 nonvirtual Iterable<T> Slice (size_t from, size_t to) const;
1021
1022 public:
1023 /**
1024 * \brief return the top/largest (possibly just top N) values from this Iterable<T>
1025 *
1026 * Provide a function object that says how you want to compare the 'T' elements.
1027 * OPTIONALLY, provide a number N, saying to return the top N results (if N < size, just return size elements).
1028 *
1029 * \em Performance:
1030 * let S = this->size();
1031 * O(S) * ln (N) ; so S*log(S) if you get all of them, but if you just need the top three, its O(S)
1032 *
1033 * \par Example Usage
1034 * \code
1035 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1036 * EXPECT_TRUE (c.Top ().SequentialEquals (c.OrderBy (std::greater<int>{})));
1037 * EXPECT_TRUE (c.Top (2).SequentialEquals ({38, 9}));
1038 * EXPECT_TRUE (c.Top (2, std::greater<int>{}).SequentialEquals ({38, 9})); // same as previous line
1039 * EXPECT_TRUE (c.Top (3, std::less<int>{}).SequentialEquals ({3, 3, 5}));
1040 * \endcode
1041 *
1042 * \note Uses IPotentiallyComparer instead of IInOrderComparer since from context, if you pass in a lambda, it
1043 * should be clear about intent.
1044 */
1045 nonvirtual Iterable<T> Top () const;
1046 nonvirtual Iterable<T> Top (size_t n) const;
1047 template <Common::IPotentiallyComparer<T> COMPARER>
1048 nonvirtual Iterable<T> Top (COMPARER&& cmp) const;
1049 template <Common::IPotentiallyComparer<T> COMPARER>
1050 nonvirtual Iterable<T> Top (size_t n, COMPARER&& cmp) const;
1051
1052 public:
1053 /**
1054 * BASED ON Microsoft .net Linq.
1055 *
1056 * \par Example Usage
1057 * \code
1058 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1059 * EXPECT_TRUE (c.OrderBy ().SequentialEquals ({ 3, 3, 5, 5, 9, 38 }));
1060 * \endcode
1061 *
1062 * \par Example Usage
1063 * \code
1064 * Iterable<int> c{ 3, 5, 9, 38, 3, 5 };
1065 * EXPECT_TRUE (c.OrderBy ([](int lhs, int rhs) -> bool { return lhs < rhs; }).SequentialEquals ({ 3, 3, 5, 5, 9, 38 }));
1066 * \endcode
1067 *
1068 * \note This defaults to using seq=Execution::SequencePolicy::ePar, parallel sort, so be careful if your compare function doesn't support this - pass in
1069 * SequencePolicy::eSeq
1070 *
1071 * \note This performs a stable sort (preserving the relative order of items that compare equal).
1072 * 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.
1073 *
1074 * @aliases Sort ()
1075 *
1076 * \note Should be of type IInOrderComparer, but not required - for convenience of use (so can be used with any lambda functor)
1077 *
1078 * See:
1079 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.orderby(v=vs.110).aspx
1080 * @see IsOrderedBy ()
1081 *
1082 * \post result.IsOrderedBy (inorderComparer);
1083 */
1084 template <Common::IPotentiallyComparer<T> INORDER_COMPARER_TYPE = less<T>>
1085 nonvirtual Iterable<T> OrderBy (INORDER_COMPARER_TYPE&& inorderComparer = INORDER_COMPARER_TYPE{},
1087
1088 public:
1089 /**
1090 * @aliases IsSorted ()
1091 *
1092 * \see
1093 * OrderBy ()
1094 */
1095 template <Common::IPotentiallyComparer<T> INORDER_COMPARER_TYPE = less<T>>
1096 nonvirtual bool IsOrderedBy (INORDER_COMPARER_TYPE&& inorderComparer = INORDER_COMPARER_TYPE{}) const;
1097
1098 public:
1099 /**
1100 * \brief return first element in iterable, or if 'that' specified, first where 'that' is true, (or return nullopt if none)
1101 *
1102 * @aliases Find () - but in Stroika, Find () returns an Iterator<>
1103 *
1104 * \par Example Usage
1105 * \code
1106 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1107 * EXPECT_EQ (*c.First (), 3);
1108 * EXPECT_EQ (*c.First ([](int i){ return i % 2 == 0;}), 38);
1109 * \endcode
1110 *
1111 * \par Example Usage
1112 * \code
1113 * Collection<SomeStruct> c;
1114 * if (optional<SomeStruct> o = c.First ([=](SomeStruct smi) { return smi.fID == substanceId; })) {
1115 * something_with_o (o);
1116 * }
1117 * \endcode
1118 *
1119 * \note
1120 * BASED ON Microsoft .net Linq.
1121 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.first(v=vs.110).aspx
1122 */
1123 nonvirtual optional<T> First () const;
1124 template <invocable<T> F>
1125 nonvirtual optional<T> First (F&& that) const
1126 requires (convertible_to<invoke_result_t<F, T>, bool>);
1127 template <typename RESULT_T = T>
1128 nonvirtual optional<RESULT_T> First (const function<optional<RESULT_T> (ArgByValueType<T>)>& that) const;
1129
1130 public:
1131 /**
1132 * \brief return first element in iterable provided default
1133 *
1134 * \par Example Usage
1135 * \code
1136 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1137 * EXPECT_EQ (c.FirstValue (), 3);
1138 * \endcode
1139 *
1140 * \note
1141 * BASED ON Microsoft .net Linq. (FirstOrDefault)
1142 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.firstordefault(v=vs.110).aspx
1143 */
1144 nonvirtual T FirstValue (ArgByValueType<T> defaultValue = {}) const;
1145 template <invocable<T> F>
1146 nonvirtual T FirstValue (F&& that, ArgByValueType<T> defaultValue = {}) const
1147 requires (convertible_to<invoke_result_t<F, T>, bool>);
1148
1149 public:
1150 /**
1151 * \brief return last element in iterable, or if 'that' specified, last where 'that' is true, (or return missing)
1152 *
1153 * \par Example Usage
1154 * \code
1155 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1156 * EXPECT_EQ (*c.Last (), 5);
1157 * EXPECT_EQ (*c.Last ([](int i){ return i % 2 == 0;}), 38);
1158 * \endcode
1159 *
1160 * \note
1161 * BASED ON Microsoft .net Linq. (Last)
1162 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.last(v=vs.110).aspx
1163 */
1164 nonvirtual optional<T> Last () const;
1165 template <invocable<T> F>
1166 nonvirtual optional<T> Last (F&& that) const
1167 requires (convertible_to<invoke_result_t<F, T>, bool>);
1168 template <typename RESULT_T = T>
1169 nonvirtual optional<RESULT_T> Last (const function<optional<RESULT_T> (ArgByValueType<T>)>& that) const;
1170
1171 public:
1172 /**
1173 * BASED ON Microsoft .net Linq. (LastOrDefault)
1174 *
1175 * \par Example Usage
1176 * \code
1177 * Iterable<int> c { 3, 5, 9, 38, 3, 5 };
1178 * EXPECT_EQ (c.LastValue (), 5);
1179 * \endcode
1180 *
1181 * See:
1182 * @see https://msdn.microsoft.com/en-us/library/system.linq.enumerable.lastordefault(v=vs.110).aspx
1183 */
1184 nonvirtual T LastValue (ArgByValueType<T> defaultValue = {}) const;
1185 template <invocable<T> F>
1186 nonvirtual T LastValue (F&& that, ArgByValueType<T> defaultValue = {}) const
1187 requires (convertible_to<invoke_result_t<F, T>, bool>);
1188
1189 public:
1190 /**
1191 * \brief return true iff argument predicate returns true for each element of the iterable
1192 *
1193 * \par Example Usage
1194 * \code
1195 * Iterable<int> c { 3, 5, 9, 3, 5 };
1196 * EXPECT_TRUE (c.All ([](int i){ return i % 2 == 1;}));
1197 * \endcode
1198 *
1199 * \note
1200 * BASED ON Microsoft .net Linq. (Last)
1201 * @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.all?view=netframework-4.7.2
1202 *
1203 * @see also Iterable<T>::Where ()
1204 */
1205 nonvirtual bool All (const function<bool (ArgByValueType<T>)>& testEachElt) const;
1206
1207 public:
1208 /**
1209 * BASED ON Microsoft .net Linq.
1210 *
1211 * \par Example Usage
1212 * \code
1213 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1214 * EXPECT_TRUE (c.Min () == 1);
1215 * \endcode
1216 *
1217 * \note returns nullopt if empty list
1218 *
1219 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return min (lhs, rhs); })
1220 *
1221 * See:
1222 * https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
1223 * @Max
1224 */
1225 nonvirtual optional<T> Min () const;
1226
1227 public:
1228 /**
1229 * @see @Max
1230 */
1231 template <typename RESULT_TYPE = T>
1232 nonvirtual RESULT_TYPE MinValue (ArgByValueType<RESULT_TYPE> defaultValue = {}) const;
1233
1234 public:
1235 /**
1236 * BASED ON Microsoft .net Linq.
1237 *
1238 * EXAMPLE:
1239 * \code
1240 * Iterable<int> c { 1, 2, 3, 4, 5, 6 };
1241 * EXPECT_TRUE (c.Max () == 6);
1242 * \endcode
1243 *
1244 * \note returns nullopt if empty list
1245 *
1246 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return max (lhs, rhs); })
1247 *
1248 * See:
1249 * https://msdn.microsoft.com/en-us/library/bb503062%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
1250 * @Min
1251 */
1252 nonvirtual optional<T> Max () const;
1253
1254 public:
1255 /**
1256 * @see @Max
1257 */
1258 template <typename RESULT_TYPE = T>
1259 nonvirtual RESULT_TYPE MaxValue (ArgByValueType<RESULT_TYPE> defaultValue = {}) const;
1260
1261 public:
1262 /**
1263 * BASED ON Microsoft .net Linq.
1264 *
1265 * \par Example Usage
1266 * \code
1267 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
1268 * EXPECT_EQ (c.Mean (), 4);
1269 * \endcode
1270 *
1271 * \note returns nullopt if empty list
1272 *
1273 * AKA "Average"
1274 *
1275 * See:
1276 * https://msdn.microsoft.com/en-us/library/bb548647(v=vs.100).aspx
1277 */
1278 template <typename RESULT_TYPE = T>
1279 nonvirtual optional<RESULT_TYPE> Mean () const;
1280
1281 public:
1282 /**
1283 * @see @Mean
1284 */
1285 template <typename RESULT_TYPE = T>
1286 nonvirtual RESULT_TYPE MeanValue (ArgByValueType<RESULT_TYPE> defaultValue = {}) const;
1287
1288 public:
1289 /**
1290 * BASED ON Microsoft .net Linq.
1291 *
1292 * \par Example Usage
1293 * \code
1294 * Iterable<int> c { 1, 2, 3, 4, 5, 9 };
1295 * EXPECT_TRUE (c.Sum () == 24);
1296 * \endcode
1297 *
1298 * \note Equivalent to Reduce ([] (T lhs, T rhs) { return lhs + rhs; })
1299 *
1300 * \note returns nullopt if empty list
1301 *
1302 * See:
1303 * https://msdn.microsoft.com/en-us/library/system.linq.enumerable.sum(v=vs.110).aspx
1304 */
1305 template <typename RESULT_TYPE = T>
1306 nonvirtual optional<RESULT_TYPE> Sum () const;
1307
1308 public:
1309 /**
1310 * @see @Sum
1311 */
1312 template <typename RESULT_TYPE = T>
1313 nonvirtual RESULT_TYPE SumValue (ArgByValueType<RESULT_TYPE> defaultValue = {}) const;
1314
1315 public:
1316 /**
1317 * \par Example Usage
1318 * \code
1319 * Iterable<int> c { 1, 2, 9, 4, 5, 3 };
1320 * EXPECT_TRUE (NearlyEquals (c.Median (), 3.5));
1321 * \endcode
1322 *
1323 * \note returns nullopt if empty list
1324 *
1325 * \note Should be of type IInOrderComparer, but not required - for convenience of use (so can be used with any lambda functor)
1326 * \todo probably TIGHTEN THIS - and require ITotallyOrdering.... - so can use either less compare or strong compare function.
1327 */
1328 template <constructible_from<T> RESULT_TYPE = T, Common::IPotentiallyComparer<RESULT_TYPE> INORDER_COMPARE_FUNCTION = less<RESULT_TYPE>>
1329 nonvirtual optional<RESULT_TYPE> Median (const INORDER_COMPARE_FUNCTION& compare = {}) const;
1330
1331 public:
1332 /**
1333 * @see @Median
1334 */
1335 template <constructible_from<T> RESULT_TYPE = T>
1336 nonvirtual RESULT_TYPE MedianValue (ArgByValueType<RESULT_TYPE> defaultValue = {}) const;
1337
1338 public:
1339 /**
1340 * Return this iterable n (count) times. count may be zero, or any other unsigned integer.
1341 * Repeat (0) returns an empty list, and Repeat (1) returns *this;
1342 *
1343 * Similar to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.repeat?view=netcore-3.1
1344 *
1345 * \par Example Usage
1346 * \code
1347 * Iterable<int> c{1};
1348 * EXPECT_TRUE (c.Repeat (5).SequentialEquals ({1, 1, 1, 1, 1}));
1349 * \endcode
1350 */
1351 nonvirtual Iterable<T> Repeat (size_t count) const;
1352
1353 public:
1354 /**
1355 * \brief Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any values in iterable
1356 *
1357 * \note
1358 * BASED ON Microsoft .net Linq. (Last)
1359 * @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__
1360 *
1361 * \note @see Count
1362 * \note @see Where
1363 * @aliases AnyThat (predicate)
1364 */
1365 nonvirtual bool Any () const;
1366 nonvirtual bool Any (const function<bool (ArgByValueType<T>)>& includeIfTrue) const;
1367
1368 public:
1369 /**
1370 * \brief with no args, same as size, with function filter arg, returns number of items that pass.
1371 *
1372 * \note
1373 * BASED ON Microsoft .net Linq. (Count)
1374 * @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.count?view=net-6.0
1375 *
1376 * \note Count/1 same as Where (i).size ();
1377 * \note @see Any
1378 */
1379 nonvirtual size_t Count () const;
1380 nonvirtual size_t Count (const function<bool (ArgByValueType<T>)>& includeIfTrue) const;
1381
1382 public:
1383 /**
1384 * \brief STL-ish alias for size() - really in STL only used in string, I think, but still makes sense as an alias.
1385 */
1386 nonvirtual size_t length () const;
1387
1388 protected:
1389 /**
1390 * @see Memory::SharedByValue_State
1391 *
1392 * Don't call this lightly. This is just meant for low level or debugging, and for subclass optimizations
1393 * based on the state of the shared common object.
1394 */
1396
1397 private:
1398 static shared_ptr<_IRep> Clone_ (const _IRep& rep);
1399
1400 private:
1401#if (__cplusplus < kStrokia_Foundation_Common_cplusplus_20) || qCompilerAndStdLib_lambdas_in_unevaluatedContext_Buggy
1402 struct Rep_Cloner_ {
1403 auto operator() (const _IRep& t) const -> shared_ptr<_IRep>
1404 {
1405 return Iterable<T>::Clone_ (t);
1406 }
1407 };
1408#else
1409 using Rep_Cloner_ = decltype ([] (const _IRep& t) -> shared_ptr<_IRep> { return Iterable<T>::Clone_ (t); });
1410#endif
1411
1412 private:
1413 template <typename CONTAINER_OF_T>
1414 static Iterable<T> mk_ (CONTAINER_OF_T&& from);
1415
1416 protected:
1417 /**
1418 * \brief Lazy-copying smart pointer mostly used by implementors (can generally be ignored by users).
1419 * However, protected because manipulation needed in some subclasses (rarely) - like UpdatableIteratable.
1420 */
1422
1423 protected:
1424 template <typename REP_SUB_TYPE = _IRep>
1426
1427 protected:
1428 template <typename REP_SUB_TYPE = _IRep>
1430
1431 protected:
1432 /**
1433 * Rarely access in subclasses, but its occasionally needed, like in UpdatableIterator<T>
1434 */
1436
1437 protected:
1438 Debug::AssertExternallySynchronizedMutex _fThisAssertExternallySynchronized;
1439
1440 public:
1441 template <typename SHARED_T>
1442 using PtrImplementationTemplate [[deprecated ("Since Stroika v3.0d1 - use shared_ptr directly")]] = shared_ptr<SHARED_T>;
1443 template <typename SHARED_T, typename... ARGS_TYPE>
1444 [[deprecated ("Since Stroika v3.0d1 - use Memory::MakeSharedPtr directly")]] static shared_ptr<SHARED_T> MakeSmartPtr (ARGS_TYPE&&... args)
1445 {
1446 return Memory::MakeSharedPtr<SHARED_T> (forward<ARGS_TYPE> (args)...);
1447 }
1448 template <typename SHARED_T>
1449 using enable_shared_from_this_PtrImplementationTemplate [[deprecated ("Since Stroika v3.0d1")]] = std::enable_shared_from_this<SHARED_T>;
1450
1451 protected:
1452 using _IterableRepSharedPtr [[deprecated ("Since Stroika v3.0d1 use shared_ptr<_IRep> directly")]] = shared_ptr<_IRep>;
1453 using _IteratorRepSharedPtr [[deprecated ("Since Stroika v3.0d1 use unique_ptr<typename Iterator<T>::IRep> directly")]] =
1454 unique_ptr<typename Iterator<T>::IRep>;
1455 };
1456
1457#if qCompilerAndStdLib_lambdas_in_unevaluatedContext_warning_Buggy
1458 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wsubobject-linkage\"")
1459#endif
1460
1461 /**
1462 * _SafeReadRepAccessor is used by Iterable<> subclasses to assure thread safety. It takes the
1463 * 'this' object, and captures a const reference to the internal 'REP'.
1464 *
1465 * For DEBUGGING (catching races) purposes, it also locks the Debug::AssertExternallySynchronizedMutex,
1466 * so that IF this object is accessed illegally by other threads while in use (this use), it will
1467 * be caught.
1468 *
1469 * \note _SafeReadRepAccessor also provides type safety, in that you template in the subtype
1470 * of the REP object, and we store a single pointer, but cast to the appropriate subtype.
1471 *
1472 * This supports type safe usage because in DEBUG builds we check (AssertMember)
1473 * the dynamic type, and if you structure your code to assure a given type (say Collection<T>)
1474 * only passes in to pass class appropriately typed objects, and just use that type in
1475 * your _SafeReadRepAccessor<> use, you should be safe.
1476 *
1477 * @see _SafeReadWriteRepAccessor
1478 */
1479 template <typename T>
1480 template <typename REP_SUB_TYPE>
1482 public:
1483 _SafeReadRepAccessor () = delete;
1486 _SafeReadRepAccessor (const Iterable<T>* it) noexcept;
1487
1488 public:
1489 nonvirtual _SafeReadRepAccessor& operator= (const _SafeReadRepAccessor&) = delete;
1490 nonvirtual _SafeReadRepAccessor& operator= (_SafeReadRepAccessor&& rhs) noexcept;
1491
1492 public:
1493 nonvirtual const REP_SUB_TYPE& _ConstGetRep () const noexcept;
1494
1495 public:
1496 nonvirtual shared_ptr<REP_SUB_TYPE> _ConstGetRepSharedPtr () const noexcept;
1497
1498 private:
1499 const REP_SUB_TYPE* fConstRef_;
1500 const Iterable<T>* fIterableEnvelope_;
1501
1502#if qStroika_Foundation_Debug_AssertionsChecked
1503 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex::ReadContext fAssertReadLock_;
1504#endif
1505 };
1506 //static_assert (movable<Iterable<int>::_SafeReadRepAccessor<REP_SUB_TYPE>> and not copyable<Iterable<int>::_SafeReadRepAccessor<REP_SUB_TYPE>>);
1507
1508 /**
1509 * _SafeReadWriteRepAccessor is used by Iterable<> subclasses to assure thread-safety. It takes the
1510 * 'this' object, and captures a writable to the internal 'REP'.
1511 *
1512 * For DEBUGGING (catching races) purposes, it also locks the Debug::AssertExternallySynchronizedMutex,
1513 * so that IF this object is accessed illegally by other threads while in use (this use), it will
1514 * be caught.
1515 *
1516 * @see _SafeReadRepAccessor
1517 *
1518 */
1519 template <typename T>
1520 template <typename REP_SUB_TYPE>
1522 public:
1523 _SafeReadWriteRepAccessor () = delete;
1526 _SafeReadWriteRepAccessor (Iterable<T>* iterableEnvelope);
1527
1528 public:
1529 nonvirtual _SafeReadWriteRepAccessor& operator= (const _SafeReadWriteRepAccessor&) = delete;
1530 nonvirtual _SafeReadWriteRepAccessor& operator= (_SafeReadWriteRepAccessor&&) noexcept;
1531
1532 public:
1533 nonvirtual const REP_SUB_TYPE& _ConstGetRep () const;
1534
1535 public:
1536 nonvirtual REP_SUB_TYPE& _GetWriteableRep ();
1537
1538 private:
1539 REP_SUB_TYPE* fRepReference_;
1540#if qStroika_Foundation_Debug_AssertionsChecked
1541 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex::WriteContext fAssertWriteLock_;
1542 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)
1543#endif
1544 };
1545 //static_assert (movable<Iterable<int>::_SafeReadWriteRepAccessor<REP_SUB_TYPE>> and not copyable<Iterable<int>::_SafeReadWriteRepAccessor<REP_SUB_TYPE>>);
1546
1547 /**
1548 * \brief Implementation detail for iterator implementors.
1549 *
1550 * Abstract class used in subclasses which extend the idea of Iterable.
1551 * Most abstract Containers in Stroika subclass of Iterable<T>.
1552 *
1553 * \note Design Note: weak_ptr vs. dangling pointers vs shared_from_this
1554 *
1555 * Prior to Stroika v3, we had a mixed API where we passed in a shared_ptr as argument to MakeIterator and sometimes
1556 * saved the shared_ptr, making the iterators safe if certain things changed. But not generally enuf to be useful and its
1557 * costly.
1558 *
1559 * 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
1560 * do/revisit - LGP 2023-07-07).
1561 *
1562 * Containers internally use fChangeCounts - in DEBUG builds - to try to assure the underlying container is not modified during iteration, and
1563 * and there are several modifying APIs that take an Iterator and return an updated Iterator to avoid this issue.
1564 *
1565 * But the main takeaway, is that Iterator<> objects must be short lived, and not used after any modification to the underlying Iterable being
1566 * iterated over.
1567 */
1568 template <typename T>
1569 class Iterable<T>::_IRep {
1570 protected:
1571 _IRep () = default;
1572
1573 public:
1574 virtual ~_IRep () = default;
1575
1576 public:
1577 /**
1578 */
1579 virtual shared_ptr<_IRep> Clone () const = 0;
1580
1581 public:
1582 /**
1583 * This returns an object owning INTERNAL POINTERS to the thing being iterated over. It's a potentially
1584 * undetected error to ever operate on the iterator after the Iterable has been modified (many Stroika classes like containers
1585 * will detect this error in debug builds).
1586 */
1588
1589 public:
1590 /**
1591 * returns the number of elements in iterable. Equivalent to (and defaults to)
1592 * i = MakeIterator, followed by counting number of iterations til the end.
1593 */
1594 virtual size_t size () const;
1595
1596 public:
1597 /**
1598 * returns the true if MakeIterator() returns an empty iterator.
1599 */
1600 virtual bool empty () const;
1601
1602 public:
1603 /**
1604 * Apply the given doToElement function to every element of the Iterable (in some arbitrary order).
1605 */
1606 virtual void Apply (const function<void (ArgByValueType<T> item)>& doToElement, Execution::SequencePolicy seq) const;
1607
1608 public:
1609 /*
1610 * \see _IRep::MakeIterator for rules about lifetime of returned Iterator<T>
1611 * Defaults to, and is equivalent to, walking the Iterable, and applying 'that' function, and returning the first (depending on seq) entry that
1612 * returns true, or empty iterator if none does.
1613 */
1614 virtual Iterator<value_type> Find (const function<bool (ArgByValueType<T> item)>& that, Execution::SequencePolicy seq) const;
1615
1616 public:
1617 /**
1618 * Find_equal_to is Not LOGICALLY needed, as you can manually iterate (just use Find()).
1619 * But this CAN be much faster (and commonly is) - and is used very heavily by iterables, so
1620 * its worth the singling out of this important special case.
1621 *
1622 * \pre Common::IEqualToOptimizable<T>; would like to only define (with requires) but
1623 * cannot seem to do in C++20 - requires on virtual function
1624 *
1625 * Default implemented as
1626 * \code
1627 * return Find ([] (const T& lhs) { return equal_to<T>{}(lhs, v); }, seq);
1628 * \endcode
1629 *
1630 * \see _IRep::MakeIterator for rules about lifetime of returned Iterator<T>
1631 */
1632 virtual Iterator<value_type> Find_equal_to (const ArgByValueType<T>& v, Execution::SequencePolicy seq) const;
1633 };
1634
1635 /**
1636 * Compare any two iterables as a sequence of elements that can themselves be compared - like strcmp().
1637 * The first pair which is unequally compared - defines the ordering relationship between the two iterables.
1638 * And if one ends before the other, if the LHS ends first, treat that as less (like with alphabetizing) and
1639 * if the right ends first, treat that as >.
1640 *
1641 * \note If useIterableSize == true (Defaults false), size() method must be quick, and unchanged during the lifetime of the the comparison.
1642 *
1643 * SequentialEqualsComparer is commutative().
1644 *
1645 * Computational Complexity: O(N)
1646 */
1647 template <typename T>
1648 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IEqualsComparer<T>) T_EQUALS_COMPARER>
1649 struct Iterable<T>::SequentialEqualsComparer : Common::ComparisonRelationDeclarationBase<Common::ComparisonRelationType::eEquals> {
1650 constexpr SequentialEqualsComparer (const T_EQUALS_COMPARER& elementComparer = {}, bool useIterableSize = false);
1651 nonvirtual bool operator() (const Iterable& lhs, const Iterable& rhs) const;
1652 [[no_unique_address]] T_EQUALS_COMPARER fElementComparer;
1653 bool fUseIterableSize;
1654 };
1655
1656 /**
1657 * Compare any two iterables as a sequence of elements that can themselves be compared - like strcmp().
1658 * The first pair which is unequally compared - defines the ordering relationship between the two iterables.
1659 * And if one ends before the other, if the LHS ends first, treat that as less (like with alphabetizing) and
1660 * if the right ends first, treat that as >.
1661 */
1662 template <typename T>
1663 template <qCompilerAndStdLib_ConstraintDiffersInTemplateRedeclaration_BWA (IThreeWayComparer<T>) T_THREEWAY_COMPARER>
1664 struct Iterable<T>::SequentialThreeWayComparer : Common::ComparisonRelationDeclarationBase<Common::ComparisonRelationType::eThreeWayCompare> {
1665 constexpr SequentialThreeWayComparer (const T_THREEWAY_COMPARER& elementComparer = {});
1666 nonvirtual auto operator() (const Iterable& lhs, const Iterable& rhs) const;
1667 [[no_unique_address]] T_THREEWAY_COMPARER fElementComparer;
1668 };
1669
1670 // see Satisfies Concepts
1671 // @todo would be nice to include these tests generically as part of template declaration, but cannot figure out how
1672 // to get that working (probably due to when incomplete types evaluated) --LGP 2024-08-21
1673 static_assert (copyable<Iterable<int>>);
1674
1675}
1676
1677/*
1678 ********************************************************************************
1679 ******************************* Implementation Details *************************
1680 ********************************************************************************
1681 */
1682#include "Iterable.inl"
1683
1684#endif /*_Stroika_Foundation_Traversal_Iterable_h_ */
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...
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
Implementation detail for iterator implementors.
Definition Iterable.h:1569
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:237
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 void Apply(const function< void(ArgByValueType< T > item)> &doToElement, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument function (or lambda) on each element of the container.
nonvirtual RESULT_TYPE MaxValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual Iterable< T > Slice(size_t from, size_t to) const
Definition Iterable.inl:701
nonvirtual Iterator< T > Find(THAT_FUNCTION &&that, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument bool-returning function (or lambda) on each element of the container,...
static bool SetEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
Definition Iterable.inl:320
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
Definition Iterable.inl:984
nonvirtual RESULT_TYPE MedianValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual optional< RESULT_TYPE > Mean() const
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 Iterable< T > Top() const
return the top/largest (possibly just top N) values from this Iterable<T>
Definition Iterable.inl:777
nonvirtual CONTAINER_OF_T As(CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
nonvirtual Iterable< T > Distinct(EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
functional API which iterates over all members of an Iterable, applies a map function to each element...
nonvirtual size_t Count() const
with no args, same as size, with function filter arg, returns number of items that pass.
nonvirtual bool IsOrderedBy(INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
nonvirtual Iterable< T > Repeat(size_t count) const
nonvirtual Memory::SharedByValue_State _GetSharingState() const
Definition Iterable.inl:289
nonvirtual optional< T > First() const
return first element in iterable, or if 'that' specified, first where 'that' is true,...
Definition Iterable.inl:829
T value_type
value_type is an alias for the type iterated over - like vector<T>::value_type
Definition Iterable.h:248
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
Definition Iterable.inl:940
nonvirtual bool Contains(ArgByValueType< T > element, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
nonvirtual optional< T > Min() const
Definition Iterable.inl:973
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:300
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 T Nth(ptrdiff_t n) const
Find the Nth element of the Iterable<>
nonvirtual Iterable< T > Take(size_t nItems) const
Definition Iterable.inl:678
nonvirtual RESULT_TYPE MeanValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
nonvirtual optional< RESULT_TYPE > Median(const INORDER_COMPARE_FUNCTION &compare={}) const
nonvirtual Iterable< T > OrderBy(INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}, Execution::SequencePolicy seq=Execution::SequencePolicy::ePar) const
nonvirtual Iterable< T > Skip(size_t nItems) const
Definition Iterable.inl:655
nonvirtual RESULT_TYPE SumValue(ArgByValueType< RESULT_TYPE > defaultValue={}) const
static const function< RESULT_T(T)> kDefaultToStringConverter
Definition Iterable.h:879
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.
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 bool empty() const
Returns true iff size() == 0.
Definition Iterable.inl:306
nonvirtual T LastValue(ArgByValueType< T > defaultValue={}) const
Definition Iterable.inl:928
static bool SequentialEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}, bool useIterableSize=false)
Definition Iterable.inl:396
static bool MultiSetEquals(const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
Definition Iterable.inl:361
nonvirtual optional< T > Last() const
return last element in iterable, or if 'that' specified, last where 'that' is true,...
Definition Iterable.inl:888
nonvirtual T FirstValue(ArgByValueType< T > defaultValue={}) const
return first element in iterable provided default
Definition Iterable.inl:876
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 Iterator< T > MakeIterator() const
Create an iterator object which can be used to traverse the 'Iterable'.
Definition Iterable.inl:294
An Iterator<T> is a copyable object which allows traversing the contents of some container....
Definition Iterator.h:225
String UnoverloadedToString(const T &t)
same as ToString()/1 - but without the potentially confusing multi-arg overloads (confused some templ...
Definition ToString.inl:476
const function< String(String, String, bool)> kDefaultStringCombiner
Definition String.inl:1313
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
Definition TypeHints.h:32
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...
@ ePar
must synchronize shared data, can use mutex (or atomics), cuz each parallel execution in real thread
function object whose action is to map its argument, back to the same value it started with (identity...