#pragma once #include "CoreTypes.h" #include "Memory/Address.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Iterator.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) template inline constexpr bool bEnableBorrowedRange = false; NAMESPACE_BEGIN(Range) /** @return The iterator to the beginning of a container. */ template requires ((CLValueReference || bEnableBorrowedRange>) && requires(T&& Container) { { Container.Begin() } -> CInputOrOutputIterator; }) NODISCARD FORCEINLINE constexpr auto Begin(T&& Container) { return Container.Begin(); } /** Overloads the Begin algorithm for arrays. */ template requires ((CLValueReference || bEnableBorrowedRange>) && CArray>) NODISCARD FORCEINLINE constexpr auto Begin(T&& Container) { return Container + 0; } /** Overloads the Begin algorithm for initializer_list. */ template NODISCARD FORCEINLINE constexpr auto Begin(initializer_list Container) { return Container.begin(); } NAMESPACE_END(Range) template using TRangeIteratorType = decltype(Range::Begin(DeclVal())); NAMESPACE_BEGIN(Range) /** @return The iterator to the end of a container. */ template requires ((CLValueReference || bEnableBorrowedRange>) && requires(T&& Container) { { Container.End() } -> CSentinelFor>; }) NODISCARD FORCEINLINE constexpr auto End(T&& Container) { return Container.End(); } /** Overloads the End algorithm for arrays. */ template requires ((CLValueReference || bEnableBorrowedRange>) && CBoundedArray>) NODISCARD FORCEINLINE constexpr auto End(T&& Container) { return Container + TExtent>; } /** Overloads the End algorithm for initializer_list. */ template NODISCARD FORCEINLINE constexpr auto End(initializer_list Container) { return Container.end(); } NAMESPACE_END(Range) template using TRangeSentinelType = decltype(Range::End(DeclVal())); NAMESPACE_BEGIN(Range) /** @return The reverse iterator to the beginning of a container. */ template requires ((CLValueReference || bEnableBorrowedRange>) && requires(T&& Container) { { Container.RBegin() } -> CInputOrOutputIterator; }) NODISCARD FORCEINLINE constexpr auto RBegin(T&& Container) { return Container.RBegin(); } /** Overloads the RBegin algorithm for synthesized. */ template requires ((CLValueReference || bEnableBorrowedRange>) && !requires(T&& Container) { { Container.RBegin() } -> CInputOrOutputIterator; } && (CSameAs, TRangeSentinelType> && CBidirectionalIterator>)) NODISCARD FORCEINLINE constexpr auto RBegin(T&& Container) { return MakeReverseIterator(Range::End(Container)); } /** @return The reverse iterator to the end of a container. */ template requires ((CLValueReference || bEnableBorrowedRange>) && requires(T&& Container) { { Container.REnd() } -> CSentinelFor()))>; }) NODISCARD FORCEINLINE constexpr auto REnd(T&& Container) { return Container.REnd(); } /** Overloads the REnd algorithm for synthesized. */ template requires ((CLValueReference || bEnableBorrowedRange>) && !requires(T&& Container) { { Container.REnd() } -> CSentinelFor()))>; } && (CSameAs, TRangeSentinelType> && CBidirectionalIterator>)) NODISCARD FORCEINLINE constexpr auto REnd(T&& Container) { return MakeReverseIterator(Range::Begin(Container)); } NAMESPACE_END(Range) template using TRangeElementType = TIteratorElementType>; template using TRangeReferenceType = TIteratorReferenceType>; template using TRangeRValueReferenceType = TIteratorRValueReferenceType>; NAMESPACE_BEGIN(Range) /** @return The pointer to the container element storage. */ template requires ((CLValueReference || bEnableBorrowedRange>) && requires(T&& Container) { { Container.GetData() } -> CSameAs>>; }) NODISCARD FORCEINLINE constexpr auto GetData(T&& Container) { return Container.GetData(); } /** Overloads the GetData algorithm for synthesized. */ template requires ((CLValueReference || bEnableBorrowedRange>) && !requires(T&& Container) { { Container.GetData() } -> CSameAs>>; } && requires(T&& Container) { { Range::Begin(Forward(Container)) } -> CContiguousIterator; }) NODISCARD FORCEINLINE constexpr auto GetData(T&& Container) { return ToAddress(Range::Begin(Forward(Container))); } NAMESPACE_END(Range) template inline constexpr bool bDisableSizedRange = false; NAMESPACE_BEGIN(Range) /** @return The number of elements in the container. */ template requires (!bDisableSizedRange> && requires(T&& Container) { { Container.Num() } -> CSameAs; }) NODISCARD FORCEINLINE constexpr size_t Num(T&& Container) { return Container.Num(); } /** Overloads the Num algorithm for arrays. */ template requires (!bDisableSizedRange> && CBoundedArray>) NODISCARD FORCEINLINE constexpr size_t Num(T&& Container) { return TExtent>; } /** Overloads the Num algorithm for synthesized. */ template requires (!bDisableSizedRange> && !requires(T&& Container) { { Container.Num() } -> CSameAs; } && !CBoundedArray> && CSizedSentinelFor, TRangeSentinelType> && CForwardIterator>) NODISCARD FORCEINLINE constexpr size_t Num(T&& Container) { return Range::End(Container) - Range::Begin(Container); } NAMESPACE_END(Range) template concept CRange = requires(R Range) { typename TRangeIteratorType; typename TRangeSentinelType; } && CInputOrOutputIterator> && CSentinelFor, TRangeIteratorType>; template concept CBorrowedRange = CRange && (CLValueReference || bEnableBorrowedRange>); template concept CSizedRange = CRange && requires(R Range) { { Range::Num(Range) } -> CConvertibleTo; }; template inline constexpr bool bEnableView = false; template concept CView = CRange && CMovable && bEnableView; template concept CInputRange = CRange && CInputIterator>; template concept COutputRange = CRange && COutputIterator, T>; template concept CForwardRange = CInputRange && CForwardIterator>; template concept CBidirectionalRange = CForwardRange && CBidirectionalIterator>; template concept CRandomAccessRange = CBidirectionalRange && CRandomAccessIterator>; template concept CContiguousRange = CRandomAccessRange && CContiguousIterator> && requires(R& Range) { { Range::GetData(Range) } -> CSameAs>>; }; template concept CCommonRange = CRange && CSameAs, TRangeSentinelType>; NAMESPACE_PRIVATE_BEGIN template struct TIsInitializerList : FFalse { }; template struct TIsInitializerList> : FTrue { }; NAMESPACE_PRIVATE_END template concept CViewableRange = CRange && ((CView> && CConstructibleFrom, R>) || (!CView> && (CLValueReference || CMovable> && !NAMESPACE_PRIVATE::TIsInitializerList>::Value))); static_assert(CRange && CContiguousRange && CCommonRange); NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END