#pragma once #include "CoreTypes.h" #include "Iterator/Iterator.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) template using TIteratorElementType = TIteratorElement; template using TIteratorPointerType = TIteratorPointer; template using TIteratorReferenceType = TIteratorReference; template requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) using TIteratorRValueReferenceType = TIteratorRValueReference; 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) { Iteration::Advance(Iter, N); return Iter; } /** @return The 'N'-th predecessor of iterator 'Iter'. */ template FORCEINLINE constexpr I Prev(I Iter, TMakeUnsigned N = 1) { Iteration::Advance(Iter, -N); return Iter; } NAMESPACE_END(Iteration) template > I> FORCEINLINE void IndirectlyCopy(I&& Iter, J&& Jter) { *Iter = *Jter; } template > I> FORCEINLINE void IndirectlyMove(I&& Iter, J&& Jter) { *Iter = MoveTemp(*Jter); } template requires (CSwappable, TIteratorReferenceType>) FORCEINLINE void IndirectlySwap(I&& Iter, J&& Jter) { Swap(*Iter, *Jter); } template concept CIndirectlyCopyable = requires(const I Iter, const J Jter) { IndirectlyCopy(Iter, Jter); }; template concept CIndirectlyMovable = requires(const I Iter, const J Jter) { IndirectlyMove(Iter, Jter); }; template concept CIndirectlySwappable = CIndirectlyReadable && CIndirectlyReadable && requires(const I Iter, const J Jter) { IndirectlySwap(Iter, Iter); IndirectlySwap(Jter, Jter); IndirectlySwap(Iter, Jter); IndirectlySwap(Jter, Iter); }; NAMESPACE_BEGIN(Iteration) /** @return The iterator to the beginning of a container. */ template requires (requires(T&& Container) { { Container.Begin() } -> CForwardIterator; }) FORCEINLINE constexpr 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 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 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 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 auto RBegin(T&& Container) { return Container.RBegin(); } /** Overloads the RBegin algorithm for arrays. */ template FORCEINLINE constexpr auto RBegin( T(& Container)[N]) { return TReverseIterator(End(Container)); } template FORCEINLINE constexpr auto RBegin( T(&& Container)[N]) { return TReverseIterator(End(Container)); } template FORCEINLINE constexpr auto RBegin(const T(& Container)[N]) { return TReverseIterator(End(Container)); } template FORCEINLINE constexpr auto RBegin(const T(&& Container)[N]) { return TReverseIterator(End(Container)); } /** Overloads the RBegin algorithm for initializer_list. */ template FORCEINLINE constexpr auto RBegin(initializer_list Container) { return TReverseIterator(Container.end()); } /** @return The reverse iterator to the end of a container. */ template requires (requires(T&& Container) { { Container.REnd() } -> CForwardIterator; }) FORCEINLINE constexpr auto REnd(T&& Container) { return Container.REnd(); } /** Overloads the REnd algorithm for arrays. */ template FORCEINLINE constexpr auto REnd( T(& Container)[N]) { return TReverseIterator(Begin(Container)); } template FORCEINLINE constexpr auto REnd( T(&& Container)[N]) { return TReverseIterator(Begin(Container)); } template FORCEINLINE constexpr auto REnd(const T(& Container)[N]) { return TReverseIterator(Begin(Container)); } template FORCEINLINE constexpr auto REnd(const T(&& Container)[N]) { return TReverseIterator(Begin(Container)); } /** Overloads the REnd algorithm for initializer_list. */ template FORCEINLINE constexpr auto REnd(initializer_list Container) { return TReverseIterator(Container.begin()); } NAMESPACE_END(Iteration) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END