#pragma once #include "CoreTypes.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Compare.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_PRIVATE_BEGIN template using WithReference = T&; template struct TIteratorElementType { using Type = typename I::ElementType; }; template struct TIteratorElementType { using Type = T; }; NAMESPACE_PRIVATE_END template concept CReferenceable = requires { typename NAMESPACE_PRIVATE::WithReference; }; template concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; }; template using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType::Type; template using TIteratorReferenceType = decltype(*DeclVal()); template requires (requires(T& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal())); template concept CIndirectlyReadable = requires(const I Iter) { typename TIteratorElementType; typename TIteratorReferenceType; typename TIteratorRValueReferenceType; { *Iter } -> CSameAs>; { MoveTemp(*Iter) } -> CSameAs>; } && CCommonReference&&, TIteratorElementType&> && CCommonReference&&, TIteratorRValueReferenceType&&> && CCommonReference&&, const TIteratorElementType&>; template concept CIndirectlyWritable = requires(I && Iter, T && A) { *Iter = Forward(A); *Forward(Iter) = Forward(A); const_cast&&>(*Iter) = Forward(A); const_cast&&>(*Forward(Iter)) = Forward(A); }; template concept CWeaklyIncrementable = CDefaultConstructible && CMovable && requires(I Iter) { { ++Iter } -> CSameAs; Iter++; }; template concept CIncrementable = CRegular && CWeaklyIncrementable && requires(I Iter) { { Iter++ } -> CSameAs; }; template concept CInputOrOutputIterator = CWeaklyIncrementable && requires(I Iter) { { *Iter } -> CReferenceable; }; template concept CSentinelFor = CSemiregular && CInputOrOutputIterator && CWeaklyEqualityComparable; template inline constexpr bool bDisableSizedSentinelFor = false; template concept CSizedSentinelFor = CSentinelFor && !bDisableSizedSentinelFor, TRemoveCV> && requires(const I& Iter, const S& Sentinel) { Sentinel - Iter; Iter - Sentinel; }; template concept CInputIterator = CInputOrOutputIterator && CIndirectlyReadable; template concept COutputIterator = CInputOrOutputIterator && CIndirectlyWritable && requires(I Iter, T&& A) { *Iter++ = Forward(A); }; template concept CForwardIterator = CInputIterator && CIncrementable && CSentinelFor; template concept CBidirectionalIterator = CForwardIterator && requires(I Iter) { { --Iter } -> CSameAs; { Iter-- } -> CSameAs; }; template concept CRandomAccessIterator = CBidirectionalIterator && CTotallyOrdered && CSizedSentinelFor && requires(I Iter, const I Jter, const ptrdiff N) { { Iter += N } -> CSameAs; { Jter + N } -> CSameAs; { N + Jter } -> CSameAs; { Iter -= N } -> CSameAs; { Jter - N } -> CSameAs; { Jter[N] } -> CSameAs>; }; template concept CContiguousIterator = CRandomAccessIterator && CLValueReference> && CSameAs, TRemoveReference>> && requires(I& Iter) { static_cast>>(Iter); { AddressOf(*Iter) } -> CSameAs>>; }; static_assert(CContiguousIterator); /** 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. */ template FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N) { if constexpr (CRandomAccessIterator) { Iter += N; } else if constexpr (CBidirectionalIterator) { for (; N > 0; --N) ++Iter; for (; N < 0; ++N) --Iter; } else { checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented.")); for (; N > 0; --N) ++Iter; } } /** @return The number of hops from 'First' to 'Last'. */ template S> FORCEINLINE constexpr ptrdiff Distance(I First, S Last) { if constexpr (CSizedSentinelFor) { return Last - First; } else { ptrdiff Result = 0; for (; First != Last; ++First) ++Result; return Result; } } /** @return The 'N'-th successor of iterator 'Iter'. */ template FORCEINLINE constexpr I Next(I Iter, TMakeUnsigned N = 1) { Advance(Iter, N); return Iter; } /** @return The 'N'-th predecessor of iterator 'Iter'. */ template FORCEINLINE constexpr I Prev(I Iter, TMakeUnsigned N = 1) { Advance(Iter, -N); return Iter; } /** @return The iterator to the beginning of a container. */ template requires (requires(T&& Container) { { Container.Begin() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) Begin(T&& Container) { return Container.Begin(); } /** Overloads the Begin algorithm for arrays. */ template FORCEINLINE constexpr T* Begin( T(& Container)[N]) { return Container; } template FORCEINLINE constexpr T* Begin( T(&& Container)[N]) { return Container; } 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 initializer_list. */ template FORCEINLINE constexpr decltype(auto) Begin(initializer_list Container) { return Container.begin(); } /** @return The iterator to the end of a container. */ template requires (requires(T&& Container) { { Container.End() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) End(T&& Container) { return Container.End(); } /** Overloads the End algorithm for arrays. */ template FORCEINLINE constexpr T* End( T(& Container)[N]) { return Container + N; } template FORCEINLINE constexpr T* End( T(&& Container)[N]) { return Container + N; } 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 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) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END