From e3e127752e726ecfee20856294375f318d9287e6 Mon Sep 17 00:00:00 2001 From: Redstone1024 <2824517378@qq.com> Date: Thu, 5 Dec 2024 21:21:15 +0800 Subject: [PATCH] feat(miscellaneous): add basic range concepts and helper functions --- .../Source/Public/Miscellaneous/Range.h | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 Redcraft.Utility/Source/Public/Miscellaneous/Range.h diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/Range.h b/Redcraft.Utility/Source/Public/Miscellaneous/Range.h new file mode 100644 index 0000000..3fa6da0 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Miscellaneous/Range.h @@ -0,0 +1,244 @@ +#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