4#ifndef _Stroika_Foundation_Containers_DataStructures_DoublyLinkedList_h_
5#define _Stroika_Foundation_Containers_DataStructures_DoublyLinkedList_h_
7#include "Stroika/Foundation/StroikaPreComp.h"
9#include "Stroika/Foundation/Common/Common.h"
12#include "Stroika/Foundation/Containers/Common.h"
72 class ForwardIterator;
75 class BidirectionalIterator;
82 nonvirtual
bool empty ()
const;
93 nonvirtual
size_t size ()
const;
100 nonvirtual optional<T>
GetFirst ()
const;
107 nonvirtual optional<T>
GetLast ()
const;
119 nonvirtual
void push_front (ArgByValueType<T> item);
120 template <Memory::ISpanOfT<T> SPAN_T>
121 nonvirtual
void push_front (
const SPAN_T& copyFrom);
133 nonvirtual
void push_back (ArgByValueType<T> item);
134 template <Memory::ISpanOfT<T> SPAN_T>
135 nonvirtual
void push_back (
const SPAN_T& copyFrom);
163 template <
typename EQUALS_COMPARER = equal_to<T>>
164 nonvirtual
bool Contains (ArgByValueType<T> item, EQUALS_COMPARER&& equalsComparer = {})
const;
171 template <invocable<T> FUNCTION>
172 nonvirtual
void Apply (FUNCTION&& doToElement)
const;
180 template <
typename FUNCTION>
197 template <
typename EQUALS_COMPARER = equal_to<T>>
198 nonvirtual
void Remove (ArgByValueType<T> item, EQUALS_COMPARER&& equalsComparer = {});
199 nonvirtual
void Remove (
const ForwardIterator& i);
208 nonvirtual ForwardIterator
erase (
const ForwardIterator& i);
216 nonvirtual
void clear ();
224 nonvirtual T
GetAt (
size_t i)
const;
232 nonvirtual
void SetAt (
size_t i, ArgByValueType<T> item);
243 nonvirtual
void MoveIteratorHereAfterClone (ForwardIterator* pi,
const DoublyLinkedList<T>* movedFrom)
const;
248 nonvirtual ForwardIterator begin ()
const;
253 constexpr ForwardIterator end () const noexcept;
260 nonvirtual
void SetAt (const ForwardIterator& i, ArgByValueType<T> newValue);
269 nonvirtual
void AddBefore (const ForwardIterator& i, ArgByValueType<T> item);
276 nonvirtual
void AddAfter (const ForwardIterator& i, ArgByValueType<T> item);
279 nonvirtual
void Invariant () const noexcept;
288#if qStroika_Foundation_Debug_AssertionsChecked
290 virtual void Invariant_ () const noexcept;
294 friend class ForwardIterator;
295 friend class BidirectionalIterator;
302 template <
typename T>
303 class DoublyLinkedList<T>::Link_ :
public Memory::UseBlockAllocationIfAppropriate<Link_, sizeof (T) <= 1024> {
306 Link_ (const Link_&) = delete;
307 constexpr Link_ (ArgByValueType<T> item, Link_* prev, Link_* next);
311 Link_* fPrev{nullptr};
312 Link_* fNext{nullptr};
325 template <typename T>
326 class DoublyLinkedList<T>::ForwardIterator {
329 using iterator_category = forward_iterator_tag;
330 using value_type = DoublyLinkedList::value_type;
331 using difference_type = ptrdiff_t;
332 using pointer = const value_type*;
333 using reference = const value_type&;
341 constexpr ForwardIterator () noexcept = default;
342 explicit constexpr ForwardIterator (const DoublyLinkedList* data) noexcept;
343 explicit constexpr ForwardIterator (const DoublyLinkedList* data, UnderlyingIteratorRep startAt) noexcept;
344 constexpr ForwardIterator (const ForwardIterator&) noexcept = default;
345 constexpr ForwardIterator (ForwardIterator&&) noexcept = default;
348 nonvirtual ForwardIterator& operator= (const ForwardIterator&) = default;
349 nonvirtual ForwardIterator& operator= (ForwardIterator&&) noexcept = default;
355 explicit operator bool () const;
358 nonvirtual bool AtEnd () const noexcept;
361 nonvirtual const T& operator* () const;
364 nonvirtual const T* operator->() const;
367 nonvirtual ForwardIterator& operator++ () noexcept;
368 nonvirtual ForwardIterator operator++ (int) noexcept;
380 nonvirtual UnderlyingIteratorRep GetUnderlyingIteratorRep () const;
383 nonvirtual void SetUnderlyingIteratorRep (UnderlyingIteratorRep l);
392 nonvirtual bool operator== (const ForwardIterator& rhs) const;
395 nonvirtual void Invariant () const noexcept;
398 const Link_* _fCurrent{
nullptr};
401#if qStroika_Foundation_Debug_AssertionsChecked
402 const DoublyLinkedList* fData_{
nullptr};
405#if qStroika_Foundation_Debug_AssertionsChecked
407 nonvirtual
void Invariant_ () const noexcept;
411 friend class DoublyLinkedList;
415 static_assert (forward_iterator<typename DoublyLinkedList<int>::ForwardIterator>);
416 static_assert (regular<typename DoublyLinkedList<int>::ForwardIterator>);
425 template <
typename T>
426 class DoublyLinkedList<T>::BidirectionalIterator :
public ForwardIterator {
428 using inherited = ForwardIterator;
432 using iterator_category = bidirectional_iterator_tag;
433 using value_type = DoublyLinkedList::value_type;
434 using difference_type = ptrdiff_t;
435 using pointer =
const value_type*;
436 using reference =
const value_type&;
444 constexpr BidirectionalIterator () noexcept = default;
445 explicit constexpr BidirectionalIterator (const DoublyLinkedList* data) noexcept;
446 explicit constexpr BidirectionalIterator (const DoublyLinkedList* data, UnderlyingIteratorRep startAt) noexcept;
447 constexpr BidirectionalIterator (const BidirectionalIterator&) noexcept = default;
448 constexpr BidirectionalIterator (BidirectionalIterator&&) noexcept = default;
451 nonvirtual BidirectionalIterator& operator= (const BidirectionalIterator&) = default;
452 nonvirtual BidirectionalIterator& operator= (BidirectionalIterator&&) noexcept = default;
455 nonvirtual
bool AtStart () const noexcept;
461 nonvirtual BidirectionalIterator& operator++ () noexcept;
462 nonvirtual BidirectionalIterator operator++ (
int) noexcept;
468 nonvirtual BidirectionalIterator& operator-- () noexcept;
469 nonvirtual BidirectionalIterator operator-- (
int) noexcept;
475 nonvirtual BidirectionalIterator operator- (ptrdiff_t i) const;
478 const DoublyLinkedList* fData_{
nullptr};
482 static_assert (bidirectional_iterator<typename DoublyLinkedList<int>::BidirectionalIterator>);
483 static_assert (regular<typename DoublyLinkedList<int>::BidirectionalIterator>);
486 static_assert (ranges::input_range<DoublyLinkedList<int>>);
495#include "DoublyLinkedList.inl"
const Link_ * UnderlyingIteratorRep
nonvirtual void AddBefore(const ForwardIterator &i, ArgByValueType< T > item)
nonvirtual void push_back(ArgByValueType< T > item)
nonvirtual ForwardIterator erase(const ForwardIterator &i)
nonvirtual size_t size() const
nonvirtual void Remove(ArgByValueType< T > item, EQUALS_COMPARER &&equalsComparer={})
nonvirtual void Apply(FUNCTION &&doToElement) const
nonvirtual void SetAt(size_t i, ArgByValueType< T > item)
nonvirtual optional< T > GetLast() const
nonvirtual T GetAt(size_t i) const
nonvirtual UnderlyingIteratorRep Find(FUNCTION &&firstThat) const
nonvirtual bool empty() const
nonvirtual optional< T > GetFirst() const
nonvirtual void push_front(ArgByValueType< T > item)
nonvirtual void RemoveLast()
nonvirtual void AddAfter(const ForwardIterator &i, ArgByValueType< T > item)
nonvirtual void RemoveFirst()
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
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.
constexpr void AssertDataMatches(const DoublyLinkedList *data) const
nonvirtual size_t CurrentIndex(const DoublyLinkedList *data) const