Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
Stroika::Foundation::Containers::Sequence< T > Class Template Reference

A generalization of a vector: a container whose elements are keyed by the natural numbers. More...

#include <Sequence.h>

Inheritance diagram for Stroika::Foundation::Containers::Sequence< T >:
Stroika::Foundation::Traversal::Iterable< T > Stroika::Foundation::Containers::Private::ArrayBasedContainer< Sequence_Array< T >, Sequence< T >, false > Stroika::Foundation::Containers::Private::StdVectorBasedContainer< Sequence_stdvector< T >, Sequence< T > > Stroika::Foundation::Containers::Concrete::Sequence_ChunckedArray< T, CHUNK_SIZE > Stroika::Foundation::Containers::Concrete::Sequence_DoublyLinkedList< T > Stroika::Foundation::Containers::Concrete::Sequence_LinkedList< T > Stroika::Foundation::Containers::Concrete::Sequence_SparseSortedMapping< T > Stroika::Foundation::Containers::Concrete::Sequence_Array< T > Stroika::Foundation::Containers::Concrete::Sequence_stdvector< T >

Classes

class  _IRep
 Implementation detail for Sequence<T> implementors. More...
 

Public Types

using value_type = typename inherited::value_type
 
using ArchetypeContainerType = Sequence
 
template<Common::IEqualsComparer< T > T_EQUALS_COMPARER = equal_to<T>>
using EqualsComparer = typename Iterable< value_type >::template SequentialEqualsComparer< T_EQUALS_COMPARER >
 
- Public Types inherited from Stroika::Foundation::Traversal::Iterable< T >
using value_type = T
 value_type is an alias for the type iterated over - like vector<T>::value_type
 
using iterator = Iterator< T >
 
using const_iterator = Iterator< T >
 

Public Member Functions

 Sequence ()
 
nonvirtual BidirectionalIterator< T > MakeBidirectionalIterator () const
 Create a BidirectionalIterator for this sequence (note inherited Iterable<T>::MakeIterator () returns a forward iterator, not a random access or bidirectional iterator).
 
nonvirtual RandomAccessIterator< T > MakeRandomAccessIterator () const
 Create a RandomAccessIterator for this sequence (note inherited Iterable<T>::MakeIterator () returns a forward iterator, not a random access iterator).
 
template<typename RESULT_CONTAINER = Sequence<T>, invocable< T > ELEMENT_MAPPER>
requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>)
nonvirtual RESULT_CONTAINER Map (ELEMENT_MAPPER &&elementMapper) const
 'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to Sequence, and improve that case to clone properties from this rep (such is rep type, etc).
 
template<derived_from< Iterable< T > > RESULT_CONTAINER = Sequence<T>, predicate< T > INCLUDE_PREDICATE>
nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE &&includeIfTrue) const
 
template<IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>>
nonvirtual Sequence OrderBy (INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
 
nonvirtual bool operator== (const Sequence &rhs) const
 
nonvirtual auto operator<=> (const Sequence &rhs) const
 
nonvirtual void RemoveAll ()
 RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items.
 
nonvirtual value_type GetAt (size_t i) const
 
nonvirtual void SetAt (size_t i, ArgByValueType< value_type > item)
 
nonvirtual const value_type operator[] (size_t i) const
 alias for GetAt (i) - but returning const T
 
nonvirtual TemporaryElementReference_ operator() (size_t i)
 operator() is similar to operator[] - but returning TemporaryElementReference_, and so is updatable/writable
 
template<Common::IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>>
nonvirtual optional< size_tIndexOf (ArgByValueType< value_type > i, EQUALS_COMPARER &&equalsComparer={}) const
 
nonvirtual void Insert (size_t i, ArgByValueType< value_type > item)
 
template<IInputIterator< T > ITERATOR_OF_ADDABLE, sentinel_for< ITERATOR_OF_ADDABLE > ITERATOR_OF_ADDABLE2>
nonvirtual void InsertAll (size_t i, ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
 Insert all the given items into this sequence, starting at offset 'i'.
 
nonvirtual void Prepend (ArgByValueType< value_type > item)
 
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void PrependAll (ITERABLE_OF_ADDABLE &&s)
 
nonvirtual void Append (ArgByValueType< value_type > item)
 
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void AppendAll (ITERABLE_OF_ADDABLE &&s)
 
nonvirtual void Update (const Iterator< value_type > &i, ArgByValueType< value_type > newValue, Iterator< value_type > *nextI=nullptr)
 
nonvirtual void Remove (size_t i)
 
template<typename CONTAINER_OF_ADDABLE >
nonvirtual void As (CONTAINER_OF_ADDABLE *into) const
 write this Sequence into an existing container
 
nonvirtual optional< value_typeFirst () const
 
nonvirtual value_type FirstValue (ArgByValueType< value_type > defaultValue={}) const
 
nonvirtual optional< value_typeLast () const
 
nonvirtual value_type LastValue (ArgByValueType< value_type > defaultValue={}) const
 
nonvirtual void push_back (ArgByValueType< value_type > item)
 
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void append_range (ITERABLE_OF_ADDABLE &&s)
 STL-style spelling of AppendAll () - the same operation std::vector calls append_range ()
 
nonvirtual value_type back () const
 
nonvirtual void clear ()
 
nonvirtual void insert (const Iterator< value_type > &i, ArgByValueType< value_type > item)
 
nonvirtual void erase (size_t i)
 
nonvirtual Sequenceoperator+= (ArgByValueType< value_type > item)
 Alias for Append/AppendAll ().
 
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
nonvirtual CONTAINER_OF_T As (CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
 Convert Sequence<T> losslessly into a standard supported C++ type - vector<T>, list<T>, ...
 
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
CONTAINER_OF_T As (CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
 Convert Sequence<T> losslessly into a standard supported C++ type - vector<T>, list<T>, ...
 
- Public Member Functions inherited from Stroika::Foundation::Traversal::Iterable< T >
 Iterable (const Iterable &) noexcept=default
 Iterable are safely copyable (by value). Since Iterable uses COW, this just copies the underlying pointer and increments the reference count.
 
 Iterable (Iterable &&) noexcept=default
 Iterable are safely moveable.
 
template<IIterableOfTo< T > CONTAINER_OF_T>
requires (not derived_from<remove_cvref_t<CONTAINER_OF_T>, Iterable<T>> and (copyable<remove_cvref_t<CONTAINER_OF_T>> or same_as<remove_cvref_t<CONTAINER_OF_T>, initializer_list<T>>) )
 Iterable (CONTAINER_OF_T &&from)
 
 Iterable (const initializer_list< T > &from)
 
nonvirtual operator bool () const
 
nonvirtual Iterator< T > MakeIterator () const
 Create an iterator object which can be used to traverse the 'Iterable'.
 
nonvirtual size_t size () const
 Returns the number of items contained.
 
nonvirtual bool empty () const
 Returns true iff size() == 0.
 
template<Common::IPotentiallyComparer< T > EQUALS_COMPARER = equal_to<T>>
nonvirtual bool Contains (ArgByValueType< T > element, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
 
nonvirtual Iterator< T > begin () const
 Support for ranged for, and STL syntax in general.
 
nonvirtual void Apply (const function< void(ArgByValueType< T > item)> &doToElement) const
 Run the argument function (or lambda) on each element of the container.
 
template<predicate< T > THAT_FUNCTION>
nonvirtual Iterator< T > Find (THAT_FUNCTION &&that) const
 Run the argument bool-returning function (or lambda) on the elements of the container, and return an iterator pointing at AN element for which it returned true - not necessarily the first (see the note below; use First () if you need the first).
 
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
nonvirtual CONTAINER_OF_T As (CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
 
nonvirtual T Nth (ptrdiff_t n) const
 Find the Nth element of the Iterable<>
 
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 default-value.
 
template<derived_from< Iterable< T > > RESULT_CONTAINER = Iterable<T>, predicate< T > INCLUDE_PREDICATE>
nonvirtual RESULT_CONTAINER Where (INCLUDE_PREDICATE &&includeIfTrue) const
 produce a subset of this iterable where argument function returns true
 
template<Common::IPotentiallyComparer< T > EQUALS_COMPARER = equal_to<T>>
nonvirtual Iterable< T > Distinct (EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{}) const
 
template<ranges::range RESULT_CONTAINER = Iterable<T>, invocable< T > ELEMENT_MAPPER>
requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>)
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, and collects the results in a new Iterable
 
template<typename REDUCED_TYPE = T>
nonvirtual optional< REDUCED_TYPEReduce (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 single item.
 
template<typename REDUCED_TYPE = T>
nonvirtual REDUCED_TYPE ReduceValue (const function< REDUCED_TYPE(ArgByValueType< T >, ArgByValueType< T >)> &op, ArgByValueType< REDUCED_TYPE > defaultValue={}) const
 
template<typename RESULT_T = Characters::String, invocable< T > CONVERT_TO_RESULT = decltype (kDefaultToStringConverter<>), invocable< RESULT_T, RESULT_T, bool > COMBINER = decltype (Characters::kDefaultStringCombiner)>
requires (convertible_to<invoke_result_t<CONVERT_TO_RESULT, T>, RESULT_T> and convertible_to<invoke_result_t<COMBINER, RESULT_T, RESULT_T, bool>, RESULT_T>)
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 new object (typically a string)
 
nonvirtual Iterable< T > Skip (size_t nItems) const
 
nonvirtual Iterable< T > Take (size_t nItems) const
 
nonvirtual Iterable< T > Slice (size_t from, size_t to) const
 
nonvirtual optional< T > Top () const
 return the top/largest value (or the top N values) from this Iterable<T>
 
template<Common::IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>>
nonvirtual Iterable< T > OrderBy (INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
 
template<Common::IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>>
nonvirtual bool IsOrderedBy (INORDER_COMPARER_TYPE &&inorderComparer=INORDER_COMPARER_TYPE{}) const
 
nonvirtual optional< T > First () const
 return first element in iterable, or if 'that' specified, first where 'that' is true, (or return nullopt if none)
 
nonvirtual T FirstValue (ArgByValueType< T > defaultValue={}) const
 return first element in iterable provided default
 
nonvirtual optional< T > Last () const
 return last element in iterable, or if 'that' specified, last where 'that' is true, (or return missing)
 
nonvirtual T LastValue (ArgByValueType< T > defaultValue={}) const
 
nonvirtual bool All (const function< bool(ArgByValueType< T >)> &testEachElt) const
 return true iff argument predicate returns true for each element of the iterable
 
nonvirtual optional< T > Min () const
 
template<typename RESULT_TYPE = T>
nonvirtual RESULT_TYPE MinValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const
 
nonvirtual optional< T > Max () const
 
template<typename RESULT_TYPE = T>
nonvirtual RESULT_TYPE MaxValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const
 
template<typename RESULT_TYPE = T>
nonvirtual optional< RESULT_TYPEMean () const
 
template<typename RESULT_TYPE = T>
nonvirtual RESULT_TYPE MeanValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const
 
template<typename RESULT_TYPE = T>
nonvirtual optional< RESULT_TYPESum () const
 
template<typename RESULT_TYPE = T>
nonvirtual RESULT_TYPE SumValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const
 
template<constructible_from< T > RESULT_TYPE = T, Common::IPotentiallyComparer< RESULT_TYPE > INORDER_COMPARE_FUNCTION = less<RESULT_TYPE>>
nonvirtual optional< RESULT_TYPEMedian (const INORDER_COMPARE_FUNCTION &compare={}) const
 
template<constructible_from< T > RESULT_TYPE = T>
nonvirtual RESULT_TYPE MedianValue (ArgByValueType< RESULT_TYPE > defaultValue={}) const
 
nonvirtual Iterable< T > Repeat (size_t count) const
 
nonvirtual bool Any () const
 Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any values in iterable.
 
nonvirtual size_t Count () const
 with no args, same as size, with function filter arg, returns number of items that pass.
 
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 alias.
 

Protected Member Functions

nonvirtual tuple< _IRep *, Iterator< value_type > > _GetWritableRepAndPatchAssociatedIterator (const Iterator< value_type > &i)
 Utility to get WRITABLE underlying shared_ptr (replacement for what we normally do - _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ()) but where we also handle the cloning/patching of the associated iterator.
 
- Protected Member Functions inherited from Stroika::Foundation::Traversal::Iterable< T >
 Iterable (const shared_ptr< _IRep > &rep) noexcept
 Iterable's are typically constructed as concrete subtype objects, whose CTOR passed in a shared copyable rep.
 
nonvirtual Memory::SharedByValueSupport::SharingState _GetSharingState () const
 

Additional Inherited Members

- Static Public Member Functions inherited from Stroika::Foundation::Traversal::Iterable< T >
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>>
static bool SetEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
 
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>>
static bool MultiSetEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
 
template<ranges::range LHS_CONTAINER_TYPE, ranges::range RHS_CONTAINER_TYPE, IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>>
static bool SequentialEquals (const LHS_CONTAINER_TYPE &lhs, const RHS_CONTAINER_TYPE &rhs, EQUALS_COMPARER &&equalsComparer=EQUALS_COMPARER{})
 
static constexpr default_sentinel_t end () noexcept
 Support for ranged for, and STL syntax in general.
 
- Static Public Attributes inherited from Stroika::Foundation::Traversal::Iterable< T >
template<same_as< Characters::String > RESULT_T = Characters::String>
static const function< RESULT_T(T)> kDefaultToStringConverter
 
- Protected Attributes inherited from Stroika::Foundation::Traversal::Iterable< T >
_SharedByValueRepType _fRep
 

Detailed Description

template<typename T>
class Stroika::Foundation::Containers::Sequence< T >

A generalization of a vector: a container whose elements are keyed by the natural numbers.

SmallTalk book page 153

TODO:

-> Add SetLength() method. Make sure it is optimally efficient, but try to avoid introducing a virtual function. Probably overload, and 1 arg version will use T default CTOR. If done non-virtually with templates then we only require no arg CTOR when this function called - GOOD.

Notes:

 Note: the decision on arguments to a Sort() function was difficult.

Making the arg default to op <= would not work since for type int it wouldn't be defined, and sometimes people define it as a member function, or taking const T& args. Thus the function pointer type would not match. The other alternative is to overload, and have the no arg function just have a static private CompareFunction that calls op<=. This does work pretty well, BUT it fails in cases like Sequence(Picture) where there is no op<= defined. Here, we could force the definition of this function, but that would be generally awkward and was judged not worth the trouble. Just define your own little compare function that does op <=. That simple.

The other approach sterl's been pushing is that of functional objects

described in Coplain, and the latest Stroustrup book (Nov 91). I haven't looked closely enuf to decide.

Another important addition was the CurrentIndex method. This was

decided since it allowed for easy filtering (like only third thru eight elements, or only odd elements) without keeping an extra index variable which was often very awkward. This feature will probably be seldom used, and is seldom needed, but is one of the few things that differentiate a SequenceForEach from a Sequence (ie SequenceIterator from CollectionIterator). This statement really comes down to our really only needing sequence iterators rarely, and mostly using CollectionIterators.

Note
Iterators Note that iterators always run in Sequence order, from smallest index to largest. Items inserted before the current iterator index will not be encountered, and items inserted after the current index will be encountered. Items inserted at the current index remain undefined if they will be encountered or not.

Concrete Implementations: o

See also
Concrete::Sequence_Array<> o
Concrete::Sequence_DoublyLinkedList<> o
Concrete::Sequence_LinkedList<> o
Concrete::Sequence_stdvector<>

Factory:

See also
Sequence_Factory<> to see default implementations.
Note
Thread-Safety C++-Standard-Thread-Safety
Design Note - TRAITS for equals versus COMPARER template param to methods that need it We experimented (until Stroika 2.0a20 apx) with using TRAITS that were optional with Sequence<> - and had the equals comparer. This worked OK. The advantage of having the 'equals' method in the TRAITS was that it assured (for a given instance of Sequence) that all comparisons/notions of equality were tied to the instance.

The idea WAS that you could even have a comparer that stored data in the instance (we never implemented that).

But this notion of equals has problems for defining Sequence<>::Equals() - do you use the one from the RHS or LHS?

Plus - making it a template param just added to the syntactic garbage in the template names (like in the debugger how the names printed out). This is no biggie, but it wasn't a plus.

So now (as of v2.0a20) - we just have the EQUALS_COMPARER be a templated param to the methods that need it.

Note
See ReadMe.md for common features of all Stroika containers (especially constructors, iterators, etc)
Comparisons: o static_assert (equality_comparable<T> ==> equality_comparable<Sequence<T>>); o static_assert (totally_ordered<T> ==> totally_ordered<Sequence<T>>); o using EqualsComparer = typename Iterable<T>::template SequentialEqualsComparer<T_EQUALS_COMPARER>; o using ThreeWayComparer = typename Iterable<T>::template SequentialThreeWayComparer<T_EQUALS_COMPARER>;

Definition at line 144 of file Library/Sources/Stroika/Foundation/Containers/Sequence.h.

Member Typedef Documentation

◆ value_type

◆ ArchetypeContainerType

template<typename T >
using Stroika::Foundation::Containers::Sequence< T >::ArchetypeContainerType = Sequence

Use this typedef in templates to recover the basic functional container pattern of concrete types.

Definition at line 161 of file Library/Sources/Stroika/Foundation/Containers/Sequence.h.

◆ EqualsComparer

template<typename T >
template<Common::IEqualsComparer< T > T_EQUALS_COMPARER = equal_to<T>>
using Stroika::Foundation::Containers::Sequence< T >::EqualsComparer = typename Iterable<value_type>::template SequentialEqualsComparer<T_EQUALS_COMPARER>

simply indirect to @Iterable<T>::SequentialEqualsComparer

A Sequence<T> doesn't generally require a comparison for individual elements be be defined, but obviously to compare if the containers are equal, you must compare the individual elements (at least sometimes).

If operator==(T,T) is predefined, you can just call:

Example Usage
if (a == b) {
}
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual void As(CONTAINER_OF_ADDABLE *into) const
write this Sequence into an existing container

or

}
typename Iterable< value_type >::template SequentialEqualsComparer< T_EQUALS_COMPARER > EqualsComparer

to compare with an alternative comparer.

Definition at line 335 of file Library/Sources/Stroika/Foundation/Containers/Sequence.h.

Constructor & Destructor Documentation

◆ Sequence()

template<typename T >
Stroika::Foundation::Containers::Sequence< T >::Sequence ( )

For the CTOR overload with ITERABLE_OF_ADDABLE, its anything that supports c.begin(), c.end () to find all the elements.

Note
See general information about container constructors that applies here
Example Usage
std::vector<int> v;
Sequence<int> s1 = {1, 2, 3};
Sequence<int> s4{ s1.begin (), s1.end () };
Sequence<int> s7{ v.begin (), v.end () };
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
nonvirtual Iterator< T > begin() const
Support for ranged for, and STL syntax in general.

Definition at line 241 of file Sequence.inl.

Member Function Documentation

◆ MakeBidirectionalIterator()

template<typename T >
BidirectionalIterator< T > Stroika::Foundation::Containers::Sequence< T >::MakeBidirectionalIterator ( ) const

Create a BidirectionalIterator for this sequence (note inherited Iterable<T>::MakeIterator () returns a forward iterator, not a random access or bidirectional iterator).

Note
that though this always 'works' - the returned iterator maybe quite inefficient depending on the backend implementation type.

Definition at line 285 of file Sequence.inl.

◆ MakeRandomAccessIterator()

template<typename T >
RandomAccessIterator< T > Stroika::Foundation::Containers::Sequence< T >::MakeRandomAccessIterator ( ) const

Create a RandomAccessIterator for this sequence (note inherited Iterable<T>::MakeIterator () returns a forward iterator, not a random access iterator).

Note
that though this always 'works' - the returned iterator maybe quite inefficient depending on the backend implementation type (like GetAt ()).
THIS IS WHAT YOU WANT IF ITERATOR ARITHMETIC OR ORDERING DOESN'T COMPILE.
    begin () hands back a FORWARD-only Iterator<T>, and end () is not an iterator at all -
    it is a default_sentinel_t. So 'i != s.end ()' works, but these two - both of them
    reflexes carried over from std::vector - do NOT compile:

\code
    for (auto i = s.begin (); i < s.end (); ++i) {...}   // no operator< against a sentinel
    size_t idx = i - s.begin ();                         // forward iterators have no difference
\endcode

    Neither failure names its remedy - you get a 'no matching operator' template error - so:

\code
    for (auto i = s.begin (); i != s.end (); ++i) {...}  // just use !=
    size_t idx = s.IndexOf (i);                          // position of an iterator - see IndexOf ()
    auto ri = s.MakeRandomAccessIterator ();             // or a real RA iterator: Difference (),
                                                         // operator+/-, operator--, ordering
\endcode

    Prefer IndexOf () when all you want is the position - it is one call and builds no second
    iterator. Reach for this method when you actually need the arithmetic or the ordering.

Definition at line 290 of file Sequence.inl.

◆ Where()

template<typename T >
template<derived_from< Iterable< T > > RESULT_CONTAINER = Sequence<T>, predicate< T > INCLUDE_PREDICATE>
nonvirtual RESULT_CONTAINER Stroika::Foundation::Containers::Sequence< T >::Where ( INCLUDE_PREDICATE &&  includeIfTrue) const

Apply the function function to each element, and return all the ones for which it was true.

See also
Iterable<T>::Where

◆ OrderBy()

template<typename T >
template<IPotentiallyComparer< T > INORDER_COMPARER_TYPE = less<T>>
nonvirtual Sequence Stroika::Foundation::Containers::Sequence< T >::OrderBy ( INORDER_COMPARER_TYPE &&  inorderComparer = INORDER_COMPARER_TYPE{}) const
Example Usage
Sequence<int> c { 3, 5, 9, 38, 3, 5 };
EXPECT_TRUE (c.OrderBy () == Sequence<int> { 3, 3, 5, 5, 9, 38 });
Example Usage
Sequence<int> c { 3, 5, 9, 38, 3, 5 };
EXPECT_TRUE (c.OrderBy ([](int lhs, int rhs) -> bool { return lhs < rhs; }) == Sequence<int> { 3, 3, 5, 5, 9, 38 });
Note
hides Iterable<T>::OrderBy since provides more specific types - but takes the same arguments, so the only difference is the (more specific) return type
This performs a stable sort (preserving the relative order of items that compare equal). 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.
The overload taking NO SequencePolicy leaves the choice to the implementation, exactly as Iterable<T>::OrderBy () does - see the notes there for what your comparer must guarantee (pure AND non-throwing) if you use it, and for why the current choice is sequential. Pass SequencePolicy::ePar explicitly if you are sorting something big.
This may return a different concrete type than the original Sequence<T> started with.
Aliases
Sort ()
Note
Should be of type IInOrderComparer, but not required - for convenience of use (so can be used with any lambda functor)

◆ operator==()

template<typename T >
requires (equality_comparable<T>)
bool Stroika::Foundation::Containers::Sequence< T >::operator== ( const Sequence< T > &  rhs) const

simply indirect to @Sequence<>EqualsComparer

Definition at line 851 of file Sequence.inl.

◆ operator<=>()

template<typename T >
requires (three_way_comparable<T>)
auto Stroika::Foundation::Containers::Sequence< T >::operator<=> ( const Sequence< T > &  rhs) const

simply indirect to @Sequence<>::operator

Definition at line 857 of file Sequence.inl.

◆ RemoveAll()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::RemoveAll ( )

RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items.

The no-arg overload removes all (quickly).

The overloads that remove some subset of the items returns the number of items so removed.

Note
mutates container

Definition at line 361 of file Sequence.inl.

◆ GetAt()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::GetAt ( size_t  i) const
Precondition
i < size ()

Definition at line 389 of file Sequence.inl.

◆ SetAt()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::SetAt ( size_t  i,
ArgByValueType< value_type item 
)
Precondition
i < size ()
Note
mutates container

Definition at line 396 of file Sequence.inl.

◆ operator[]()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::operator[] ( size_t  i) const

alias for GetAt (i) - but returning const T

Aliases
GetAt
Precondition
i < size ().
Note
this returns const value_type, so you cannot accidentally assign to the result a[3] = 4; // wont compile because return type const
- we investigated having operator[] (int) return TemporaryElementReference_, but the trouble is that, though this almost works, the COST of TemporaryElementReference_ is much higher than returning the cost value_type, and its not super obvious at call point that you are getting the expensive or inexpensive version (depends on constness of this pointer).

Also considered having this return T&, the way you would with std c++ vector (etc). This would avoid a lot of issues. BUT - it would BREAK the COW (copy-on-write) semantics.

Sequence<int> s{1, 2, 3};
int& r = s[0]; // hypothetical T& overload: refcount is 1, so nothing is cloned
Sequence<int> s2 = s; // an ordinary const copy - but now s and s2 SHARE one rep
r = 99; // a write aimed at s ...
// ... and s2[0] is now 99 as well, though s2 was copied before the write

COW is correct only because every write to the rep is preceded by a clone-if-shared check (_GetWriteableRep ()). Handing out a T& moves that check from WRITE time to REFERENCE-ACQUISITION time, and the reference count is free to rise in between. Unlike a non-COW container - where copying never introduces aliasing - copying a Sequence makes a previously exclusive reference shared, without anything touching the reference itself.

So because all of this, use the syntax a(3) instead of a[3] if you want a modifiable reference (to call non-const methods on or to assign to). That returns TemporaryElementReference_, which deliberately holds a Sequence*, an index, and a COPY of the value - never a pointer into the rep - and writes back through SetAt (), so the clone-if-shared check happens at the right moment.

Definition at line 403 of file Sequence.inl.

◆ operator()()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::operator() ( size_t  i)

operator() is similar to operator[] - but returning TemporaryElementReference_, and so is updatable/writable

See the notes on operator[]. The semantics of this method are similar to operator[], except that it returns a proxy object which allows (immediately) updating the element of the sequence.

Example Usage
Sequence<T> s = ...;
s(2) = 4; // s[2] = 4; WONT COMPILE

is equivalent to

auto t = s.GetAt (2);
t = 4;
s.SetAt (2, i); // note when using operator() - this SetAt() dont even if t not updated so wasteful unless updating
Precondition
i < size ()
Note
mutates container

Definition at line 410 of file Sequence.inl.

◆ IndexOf()

template<typename T >
template<Common::IEqualsComparer< T > EQUALS_COMPARER = equal_to<T>>
nonvirtual optional< size_t > Stroika::Foundation::Containers::Sequence< T >::IndexOf ( ArgByValueType< value_type i,
EQUALS_COMPARER &&  equalsComparer = {} 
) const
Search the sequence and see if the given item is contained in

it, and return the index of that item. Comparison is done with TRAITS::EqualsCompareFunctionType (which defaults to operator== (T, T)) for first two overloads - third taking iterator always works)

Note that the IndexOf(Iterator<T>) overload ignores the EQUALS_COMPARER but still must be a template method because non-template methods cannot be overloaded with template members.

If not found for the by value overloads, IndexOf () return {}; For the IndexOf(Iterator<T>) -

Precondition
it is found/legal iterator
Note
The IndexOf (Iterator<T>) overload is Stroika's answer to 'i - s.begin ()', which does not compile because begin () is a forward-only Iterator<T>. See MakeRandomAccessIterator ().

◆ Insert()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::Insert ( size_t  i,
ArgByValueType< value_type item 
)
Insert the given item into the sequence at the given index.

Any active iterators will encounter the given item if their cursor encounters the new index in the course of iteration. Put another way, If you are iterating forwards, and you add an item after what you are up to you will hit it - if you are iterating backwards and you add an item before where you are, you will hit it - otherwise you will miss the added item during iteration.

NB: Adding an item at the CURRENT index has no effect on

what the iterator says is the current item.

Note
for the Iterator<> overload, 'i' MAY be AtEnd () - in which case this appends. That includes the end () sentinel (a default_sentinel_t/nullptr-rep iterator), which has no associated iterator rep to compute an index from, so it must be special-cased rather than routed through _IRep::IndexOf ().
mutates container

Definition at line 464 of file Sequence.inl.

◆ InsertAll()

template<typename T >
template<IInputIterator< T > ITERATOR_OF_ADDABLE, sentinel_for< ITERATOR_OF_ADDABLE > ITERATOR_OF_ADDABLE2>
nonvirtual void Stroika::Foundation::Containers::Sequence< T >::InsertAll ( size_t  i,
ITERATOR_OF_ADDABLE &&  start,
ITERATOR_OF_ADDABLE2 &&  end 
)

Insert all the given items into this sequence, starting at offset 'i'.

Precondition
IInputIterator<ITERATOR_OF_ADDABLE, T> or IIterableOfTo<ITERABLE_OF_ADDABLE, T>

◆ Prepend()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::Prepend ( ArgByValueType< value_type item)
Note
mutates container

Definition at line 598 of file Sequence.inl.

◆ PrependAll()

template<typename T >
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void Stroika::Foundation::Containers::Sequence< T >::PrependAll ( ITERABLE_OF_ADDABLE &&  s)
Precondition
IInputIterator<ITERATOR_OF_ADDABLE, T> or IIterableOfTo<ITERABLE_OF_ADDABLE, T>
Note
mutates container

◆ Append()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::Append ( ArgByValueType< value_type item)

This is roughly Insert (size(), item), except that there is a race after you call size, and before Insert, which calling Append () avoids.

Note
mutates container

Definition at line 615 of file Sequence.inl.

◆ AppendAll()

template<typename T >
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void Stroika::Foundation::Containers::Sequence< T >::AppendAll ( ITERABLE_OF_ADDABLE &&  s)

This is roughly AppendAll (size(), s), except that there is a race after you call size, and before Insert, which calling Append () avoids. Also note - if used in a multithreaded environment, the appended items wont necessarily all get appended at once, since other threads could make changes in between.

Note
mutates container

◆ Update()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::Update ( const Iterator< value_type > &  i,
ArgByValueType< value_type newValue,
Iterator< value_type > *  nextI = nullptr 
)

This function requires that the iterator 'i' came from this container.

The value pointed to by 'i' is updated - replaced with the value 'newValue'.

Parameters
nextI- if provided (not null) - will be filled in with a valid iterator pointing where i is pointing - since i is invalidated by changing the container)
Note
- this differs from Collection::Update() (which advances *nextI); since for a sequence, there is no need to ever invalidate the current item on a removal (order doesnt change on update to a Sequence).
mutates container

Definition at line 716 of file Sequence.inl.

◆ Remove()

This function requires that the iterator 'i' came from this container.

The value pointed to by 'i' is removed.

Remove the item at the given position of the sequence. Make sure that iteration is not disturbed by this removal. In particular, any items (other than the one at index) that would have been seen, will still be, and no new items will be seen that wouldn't have been.

Note
mutates container

Definition at line 723 of file Sequence.inl.

◆ As() [1/3]

template<typename T >
template<typename CONTAINER_OF_ADDABLE >
nonvirtual void Stroika::Foundation::Containers::Sequence< T >::As ( CONTAINER_OF_ADDABLE *  into) const

write this Sequence into an existing container

◆ First()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::First ( ) const
See also
Iterable<T>::First ()

Definition at line 749 of file Sequence.inl.

◆ FirstValue()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::FirstValue ( ArgByValueType< value_type defaultValue = {}) const
See also
Iterable<T>::FirstValue ()

Definition at line 759 of file Sequence.inl.

◆ Last()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::Last ( ) const
See also
Iterable<T>::Last ()

Definition at line 764 of file Sequence.inl.

◆ LastValue()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::LastValue ( ArgByValueType< value_type defaultValue = {}) const
See also
Iterable<T>::LastValue ()

Definition at line 776 of file Sequence.inl.

◆ push_back()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::push_back ( ArgByValueType< value_type item)
Aliases
Append
Note
mutates container

Definition at line 782 of file Sequence.inl.

◆ append_range()

template<typename T >
template<IIterableOfTo< T > ITERABLE_OF_ADDABLE>
nonvirtual void Stroika::Foundation::Containers::Sequence< T >::append_range ( ITERABLE_OF_ADDABLE &&  s)

STL-style spelling of AppendAll () - the same operation std::vector calls append_range ()

Aliases
AppendAll

Named for C++23's vector::append_range (), which is what the standard library calls appending a whole range.

Note
mutates container

◆ back()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::back ( ) const

Read the last element (GetLast()). Requires not empty.

Definition at line 793 of file Sequence.inl.

◆ clear()

Aliases
RemoveAll ().

Definition at line 803 of file Sequence.inl.

◆ insert()

template<typename T >
void Stroika::Foundation::Containers::Sequence< T >::insert ( const Iterator< value_type > &  i,
ArgByValueType< value_type item 
)
Aliases
Insert ().
See also
https://en.cppreference.com/w/cpp/container/vector/insert
Note
- we only provide a very small subset of the possible variations of insert from STL, but this is the one needed so that Sequence<T> can be the target of Mapping<>::As<> () (and any other code doing the idiomatic 'container.insert (container.end (), value)').
- unlike std::vector<>::insert (), this returns void, not an iterator to the newly inserted item (matching Mapping<>::insert ()).
- 'i' MAY be AtEnd () - including the end () sentinel - in which case this appends.
mutates container

Definition at line 485 of file Sequence.inl.

◆ erase()

Aliases
Remove ().
Note
mutates container

Definition at line 808 of file Sequence.inl.

◆ _GetWritableRepAndPatchAssociatedIterator()

template<typename T >
auto Stroika::Foundation::Containers::Sequence< T >::_GetWritableRepAndPatchAssociatedIterator ( const Iterator< value_type > &  i)
protected

Utility to get WRITABLE underlying shared_ptr (replacement for what we normally do - _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ()) but where we also handle the cloning/patching of the associated iterator.

When you have a non-const operation (such as Remove) with an argument of an Iterator<>, then due to COW, you may end up cloning the container rep, and yet the Iterator<> contains a pointer to the earlier rep (and so maybe unusable).

Prior to Stroika 2.1b14, this was handled elegantly, and automatically, by the iterator patching mechanism. But that was deprecated (due to cost, and rarity of use), in favor of this more restricted feature, where we just patch the iterators on an as-needed basis.

Definition at line 832 of file Sequence.inl.

◆ As() [2/3]

template<typename T >
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
nonvirtual CONTAINER_OF_T Stroika::Foundation::Traversal::Iterable< T >::As ( CONTAINER_OF_T_CONSTRUCTOR_ARGS...  args) const

Convert Sequence<T> losslessly into a standard supported C++ type - vector<T>, list<T>, ...

See also
Iterable<T>::As
Note
DEPRECATED TOO - JUST USE INHERITED - BUT CANNOT LOSE TIL WE REMOVE THE OTHER DEPRECATED OVERLOAD

◆ As() [3/3]

template<typename T >
template<IIterableOfFrom< T > CONTAINER_OF_T, typename... CONTAINER_OF_T_CONSTRUCTOR_ARGS>
CONTAINER_OF_T Stroika::Foundation::Traversal::Iterable< T >::As ( CONTAINER_OF_T_CONSTRUCTOR_ARGS...  args) const

Convert Sequence<T> losslessly into a standard supported C++ type - vector<T>, list<T>, ...

See also
Iterable<T>::As
Note
DEPRECATED TOO - JUST USE INHERITED - BUT CANNOT LOSE TIL WE REMOVE THE OTHER DEPRECATED OVERLOAD

Definition at line 1432 of file Iterable.inl.


The documentation for this class was generated from the following files: