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