diff --git a/Redcraft.Utility/Source/Public/Containers/Array.h b/Redcraft.Utility/Source/Public/Containers/Array.h index 7415a13..46f0ccb 100644 --- a/Redcraft.Utility/Source/Public/Containers/Array.h +++ b/Redcraft.Utility/Source/Public/Containers/Array.h @@ -197,6 +197,9 @@ public: using Iterator = NAMESPACE_PRIVATE::TArrayIterator; using ConstIterator = NAMESPACE_PRIVATE::TArrayIterator; + using ReverseIterator = TReverseIterator< Iterator>; + using ConstReverseIterator = TReverseIterator; + static_assert(CContiguousIterator< Iterator>); static_assert(CContiguousIterator); @@ -1123,6 +1126,12 @@ public: NODISCARD FORCEINLINE constexpr ConstIterator Begin() const { return ConstIterator(this, Storage.GetPointer()); } NODISCARD FORCEINLINE constexpr Iterator End() { return Iterator(this, Storage.GetPointer() + Num()); } 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()); } /** @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 ff96b5a..ed0f748 100644 --- a/Redcraft.Utility/Source/Public/Containers/Iterator.h +++ b/Redcraft.Utility/Source/Public/Containers/Iterator.h @@ -128,6 +128,83 @@ concept CContiguousIterator = CRandomAccessIterator && CLValueReference); +/** A iterator adaptor for reverse-order traversal. */ +template +class TReverseIterator +{ +public: + + using IteratorType = I; + + using ElementType = TIteratorElementType; + + FORCEINLINE constexpr TReverseIterator() = default; + + FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default; + FORCEINLINE constexpr TReverseIterator(TReverseIterator&&) = default; + FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator&) = default; + FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default; + + 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 && 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; } + + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator) { return RHS.Current <=> LHS.Current; } + + NODISCARD FORCEINLINE constexpr ElementType& operator*() const { IteratorType Temp = Current; return *--Temp; } + NODISCARD FORCEINLINE constexpr ElementType* operator->() const { return AddressOf(operator*()); } + + 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 ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator) { return TReverseIterator(RHS.Current - LHS.Current); } + + NODISCARD FORCEINLINE constexpr IteratorType GetBase() { return Current; } + NODISCARD FORCEINLINE constexpr const IteratorType GetBase() const { return Current; } + +private: + + IteratorType Current; + + template + friend class TReverseIterator; + +}; + +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; + NAMESPACE_BEGIN(Iteration) /** Increments given iterator 'Iter' by 'N' elements. */ @@ -195,9 +272,9 @@ template FORCEINLINE constexpr T* Begin( T(&& template FORCEINLINE constexpr const T* Begin(const T(& Container)[N]) { return Container; } template FORCEINLINE constexpr const T* Begin(const T(&& Container)[N]) { return Container; } -/** Overloads the Begin algorithm for T::begin(). */ -template requires (requires(T&& Container) { { Container.begin() } -> CForwardIterator; }) -FORCEINLINE constexpr decltype(auto) Begin(T&& Container) +/** Overloads the Begin algorithm for initializer_list. */ +template +FORCEINLINE constexpr decltype(auto) Begin(initializer_list Container) { return Container.begin(); } @@ -215,13 +292,53 @@ template FORCEINLINE constexpr T* End( T(&& Co template FORCEINLINE constexpr const T* End(const T(& Container)[N]) { return Container + N; } template FORCEINLINE constexpr const T* End(const T(&& Container)[N]) { return Container + N; } -/** Overloads the End algorithm for T::end(). */ -template requires (requires(T&& Container) { { Container.end() } -> CForwardIterator; }) -FORCEINLINE constexpr decltype(auto) End(T&& Container) +/** Overloads the End algorithm for initializer_list. */ +template +FORCEINLINE constexpr decltype(auto) End(initializer_list Container) { return Container.end(); } +/** @return The reverse iterator to the beginning of a container. */ +template requires (requires(T&& Container) { { Container.RBegin() } -> CForwardIterator; }) +FORCEINLINE constexpr decltype(auto) RBegin(T&& Container) +{ + return Container.RBegin(); +} + +/** Overloads the RBegin algorithm for arrays. */ +template FORCEINLINE constexpr decltype(auto) RBegin( T(& Container)[N]) { return MakeReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin( T(&& Container)[N]) { return MakeReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin(const T(& Container)[N]) { return MakeReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin(const T(&& Container)[N]) { return MakeReverseIterator(End(Container)); } + +/** Overloads the RBegin algorithm for T::rbegin(). */ +template +FORCEINLINE constexpr decltype(auto) RBegin(initializer_list Container) +{ + return MakeReverseIterator(Container.end()); +} + +/** @return The reverse iterator to the end of a container. */ +template requires (requires(T&& Container) { { Container.REnd() } -> CForwardIterator; }) +FORCEINLINE constexpr decltype(auto) REnd(T&& Container) +{ + return Container.REnd(); +} + +/** Overloads the REnd algorithm for arrays. */ +template FORCEINLINE constexpr decltype(auto) REnd( T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd( T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd(const T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd(const T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); } + +/** Overloads the REnd algorithm for T::end(). */ +template +FORCEINLINE constexpr decltype(auto) REnd(initializer_list Container) +{ + return MakeReverseIterator(Container.begin()); +} + NAMESPACE_END(Iteration) NAMESPACE_MODULE_END(Utility)