From 273be032ec221dae79518beb105233d86e3adc2a Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Wed, 15 Feb 2023 23:36:18 +0800 Subject: [PATCH] feat(containers): add TMoveIterator and operations support --- .../Source/Public/Containers/Array.h | 14 +- .../Source/Public/Containers/Iterator.h | 172 ++++++++++++++---- 2 files changed, 147 insertions(+), 39 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Containers/Array.h b/Redcraft.Utility/Source/Public/Containers/Array.h index 46f0ccb..43555f8 100644 --- a/Redcraft.Utility/Source/Public/Containers/Array.h +++ b/Redcraft.Utility/Source/Public/Containers/Array.h @@ -235,7 +235,7 @@ public: { if constexpr (CForwardIterator) { - if constexpr (CRandomAccessIterator) checkf(First <= Last, TEXT("Illegal range iterator. Please check First <= Last.")); + if constexpr (CSizedSentinelFor) checkf(First <= Last, TEXT("Illegal range iterator. Please check First <= Last.")); const size_t Count = Iteration::Distance(First, Last); @@ -695,7 +695,7 @@ public: if constexpr (CForwardIterator) { - if constexpr (CRandomAccessIterator) checkf(First <= Last, TEXT("Illegal range iterator. Please check First <= Last.")); + if constexpr (CSizedSentinelFor) checkf(First <= Last, TEXT("Illegal range iterator. Please check First <= Last.")); const size_t InsertIndex = Iter - Begin(); const size_t Count = Iteration::Distance(First, Last); @@ -767,7 +767,7 @@ public: else { TArray Temp(MoveTemp(First), MoveTemp(Last)); - return Insert(Iter, Temp.Begin(), Temp.End()); // FIXME: Fix to MoveIterator. + return Insert(Iter, TMoveIterator(Temp.Begin()), TMoveSentinel(Temp.End())); } } @@ -1128,10 +1128,10 @@ public: NODISCARD FORCEINLINE constexpr ConstIterator End() const { return ConstIterator(this, Storage.GetPointer() + Num()); } /** @return The reverse iterator to the first or end element. */ - NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return MakeReverseIterator(End()); } - NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return MakeReverseIterator(End()); } - NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return MakeReverseIterator(Begin()); } - NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return MakeReverseIterator(Begin()); } + NODISCARD FORCEINLINE constexpr ReverseIterator RBegin() { return ReverseIterator(End()); } + NODISCARD FORCEINLINE constexpr ConstReverseIterator RBegin() const { return ConstReverseIterator(End()); } + NODISCARD FORCEINLINE constexpr ReverseIterator REnd() { return ReverseIterator(Begin()); } + NODISCARD FORCEINLINE constexpr ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); } /** @return The number of elements in the container. */ NODISCARD FORCEINLINE constexpr size_t Num() const { return Storage.GetNum(); } diff --git a/Redcraft.Utility/Source/Public/Containers/Iterator.h b/Redcraft.Utility/Source/Public/Containers/Iterator.h index ed0f748..515b9d3 100644 --- a/Redcraft.Utility/Source/Public/Containers/Iterator.h +++ b/Redcraft.Utility/Source/Public/Containers/Iterator.h @@ -86,7 +86,7 @@ template inline constexpr bool bDisableSizedSentinelFor = false; template -concept CSizedSentinelFor = CSentinelFor && !bDisableSizedSentinelFor, TRemoveCV> +concept CSizedSentinelFor = CSentinelFor && CPartiallyOrdered && !bDisableSizedSentinelFor, TRemoveCV> && requires(const I& Iter, const S& Sentinel) { Sentinel - Iter; Iter - Sentinel; }; template @@ -130,14 +130,14 @@ static_assert(CContiguousIterator); /** A iterator adaptor for reverse-order traversal. */ template -class TReverseIterator +class TReverseIterator final { public: using IteratorType = I; using ElementType = TIteratorElementType; - + FORCEINLINE constexpr TReverseIterator() = default; FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default; @@ -147,47 +147,46 @@ public: FORCEINLINE constexpr explicit TReverseIterator(IteratorType InValue) : Current(InValue) { } - template requires (!CSameAs && CConvertibleTo) - FORCEINLINE constexpr TReverseIterator(const TReverseIterator& InValue) : Current(InValue.Current) { } + template requires (!CSameAs && CConvertibleTo) + FORCEINLINE constexpr TReverseIterator(const TReverseIterator& InValue) : Current(InValue.GetBase()) { } - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.Current; return *this; } - - NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator& RHS) { return LHS.Current == RHS.Current; } + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.GetBase(); return *this; } - NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator) { return RHS.Current <=> LHS.Current; } + template requires (CWeaklyEqualityComparable) + NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator& RHS) { return LHS.GetBase() == RHS.GetBase(); } - NODISCARD FORCEINLINE constexpr ElementType& operator*() const { IteratorType Temp = Current; return *--Temp; } - NODISCARD FORCEINLINE constexpr ElementType* operator->() const { return AddressOf(operator*()); } + template requires (CThreeWayComparable) + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() <=> LHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr ElementType& operator*() const { IteratorType Temp = GetBase(); return *--Temp; } + NODISCARD FORCEINLINE constexpr ElementType* operator->() const { return AddressOf(operator*()); } + + NODISCARD FORCEINLINE constexpr ElementType& operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return GetBase()[-Index - 1]; } - NODISCARD FORCEINLINE constexpr ElementType& operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return Current[-Index - 1]; } - FORCEINLINE constexpr TReverseIterator& operator++() { --Current; return *this; } FORCEINLINE constexpr TReverseIterator& operator--() { ++Current; return *this; } - + FORCEINLINE constexpr TReverseIterator operator++(int) { TReverseIterator Temp = *this; --Current; return Temp; } FORCEINLINE constexpr TReverseIterator operator--(int) { TReverseIterator Temp = *this; ++Current; return Temp; } FORCEINLINE constexpr TReverseIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; return *this; } FORCEINLINE constexpr TReverseIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; return *this; } - - NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(TReverseIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp += Offset; return Temp; } - NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, TReverseIterator Iter) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp += Offset; return Temp; } - NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { return TReverseIterator(Current + Offset); } + NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(TReverseIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp -= Offset; return Temp; } + NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, TReverseIterator Iter) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp -= Offset; return Temp; } - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator) { return TReverseIterator(RHS.Current - LHS.Current); } + NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { return TReverseIterator(GetBase() + Offset); } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() { return Current; } - NODISCARD FORCEINLINE constexpr const IteratorType GetBase() const { return Current; } + template requires (requires(IteratorType Iter, J Jter) { { Iter - Jter } -> CSameAs; }) + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() - LHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr IteratorType GetBase() const { return Current; } private: IteratorType Current; - template - friend class TReverseIterator; - }; static_assert(CRandomAccessIterator>); @@ -195,16 +194,125 @@ static_assert(CRandomAccessIterator>); template TReverseIterator(I) -> TReverseIterator; -/** Creates a TReverseIterator of type inferred from the argument. */ -template -constexpr TReverseIterator MakeReverseIterator(I Iter) -{ - return TReverseIterator(Iter); -} - template requires (!CSizedSentinelFor) inline constexpr bool bDisableSizedSentinelFor, TReverseIterator> = true; +template +class TMoveSentinel; + +template +class TMoveIterator final +{ +public: + + using IteratorType = I; + + using ElementType = TIteratorElementType; + + FORCEINLINE constexpr TMoveIterator() = default; + + FORCEINLINE constexpr TMoveIterator(const TMoveIterator&) = default; + FORCEINLINE constexpr TMoveIterator(TMoveIterator&&) = default; + FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator&) = default; + FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default; + + FORCEINLINE constexpr explicit TMoveIterator(IteratorType InValue) : Current(InValue) { } + + template requires (!CSameAs && CConvertibleTo) + FORCEINLINE constexpr TMoveIterator(const TMoveIterator& InValue) : Current(InValue.GetBase()) { } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.GetBase(); return *this; } + + template requires (CWeaklyEqualityComparable) + NODISCARD friend FORCEINLINE constexpr bool operator==(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() == RHS.GetBase(); } + + template requires (CThreeWayComparable) + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() <=> RHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr ElementType&& operator*() const { return MoveTemp(*GetBase()); } + NODISCARD FORCEINLINE constexpr ElementType* operator->() const = delete; + + NODISCARD FORCEINLINE constexpr ElementType&& operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return MoveTemp(GetBase()[Index]); } + + FORCEINLINE constexpr TMoveIterator& operator++() { ++Current; return *this; } + FORCEINLINE constexpr TMoveIterator& operator--() requires (CBidirectionalIterator) { --Current; return *this; } + + FORCEINLINE constexpr void operator++(int) { return TMoveIterator(Current++); } + FORCEINLINE constexpr TMoveIterator operator++(int) requires (CForwardIterator) { return TMoveIterator(Current++); } + FORCEINLINE constexpr TMoveIterator operator--(int) requires (CBidirectionalIterator) { return TMoveIterator(Current--); } + + FORCEINLINE constexpr TMoveIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; return *this; } + FORCEINLINE constexpr TMoveIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; return *this; } + + NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(TMoveIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TMoveIterator Temp = Iter; Temp += Offset; return Temp; } + NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(ptrdiff Offset, TMoveIterator Iter) requires (CRandomAccessIterator) { TMoveIterator Temp = Iter; Temp += Offset; return Temp; } + + NODISCARD FORCEINLINE constexpr TMoveIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { return TMoveIterator(GetBase() - Offset); } + + template requires (requires(IteratorType Iter, J Jter) { { Iter - Jter } -> CSameAs; }) + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() - RHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr IteratorType GetBase() const { return Current; } + +private: + + IteratorType Current; + +}; + +static_assert(CRandomAccessIterator>); + +template +TMoveIterator(I) -> TMoveIterator; + +template +class TMoveSentinel +{ +public: + + using SentinelType = S; + + FORCEINLINE constexpr TMoveSentinel() = default; + + FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default; + FORCEINLINE constexpr TMoveSentinel(TMoveSentinel&&) = default; + FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel&) = default; + FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default; + + FORCEINLINE constexpr explicit TMoveSentinel(SentinelType InValue) : Last(InValue) { } + + template requires (!CSameAs && CConvertibleTo) + FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel& InValue) : Last(InValue.GetBase()) { } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel& InValue) { Last = InValue.GetBase(); return *this; } + + template requires (CSentinelFor) + NODISCARD FORCEINLINE constexpr bool operator==(const TMoveIterator& InValue) const& { return GetBase() == InValue.GetBase(); } + + template requires (CSizedSentinelFor) + NODISCARD FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& InValue) const& { return GetBase() <=> InValue.GetBase(); } + + template requires (CSizedSentinelFor) + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveSentinel& Sentinel, const TMoveIterator& Iter) { return Sentinel.GetBase() - Iter.GetBase(); } + + template requires (CSizedSentinelFor) + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); } + + NODISCARD FORCEINLINE constexpr SentinelType GetBase() const { return Last; } + +private: + + SentinelType Last; + +}; + +static_assert(CSizedSentinelFor, TMoveIterator>); + +template +TMoveSentinel(I) -> TMoveSentinel; + NAMESPACE_BEGIN(Iteration) /** Increments given iterator 'Iter' by 'N' elements. */