#pragma once #include "CoreTypes.h" #include "Memory/Address.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Iterator.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) // NOTE: The range that holds the object is called a container, and the range that only references the object is called a view. 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(Forward(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(Forward(Container))); } NAMESPACE_END(Range) NAMESPACE_PRIVATE_BEGIN template struct TRangeElementType { using Type = typename R::ElementType; }; template struct TRangeElementType { using Type = T; }; template struct TRangeElementType { using Type = T; }; NAMESPACE_PRIVATE_END template using TRangeElementType = typename NAMESPACE_PRIVATE::TRangeElementType>::Type; 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(Forward(Container)) - Range::Begin(Forward(Container)); } /** @return true if the container is empty, false otherwise. */ template requires (requires(T&& Container) { { Container.IsEmpty() } -> CBooleanTestable; }) NODISCARD FORCEINLINE constexpr bool IsEmpty(T&& Container) { return Container.IsEmpty(); } /** Overloads the IsEmpty algorithm for synthesized. */ template requires ((CBoundedArray> || requires(T&& Container) { { Container.Num() } -> CSameAs; }) && !requires(T&& Container) { { Container.IsEmpty() } -> CBooleanTestable; }) NODISCARD FORCEINLINE constexpr bool IsEmpty(T&& Container) { return Range::Num(Forward(Container)) == 0; } /** Overloads the IsEmpty algorithm for synthesized. */ template requires (!CBoundedArray> && !requires(T&& Container) { { Container.Num() } -> CSameAs; } && !requires(T&& Container) { { Container.IsEmpty() } -> CBooleanTestable; } && CForwardIterator>) NODISCARD FORCEINLINE constexpr bool IsEmpty(T&& Container) { return Range::End(Forward(Container)) == Range::Begin(Forward(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 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>; static_assert(CContiguousRange); static_assert( CCommonRange); NAMESPACE_BEGIN(Range) template requires (CClass && CSameAs>) class TViewInterface { public: /** @return The pointer to the underlying element storage. */ NODISCARD FORCEINLINE constexpr auto Data() requires (CContiguousRange< T>) { return Range::GetData(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto Data() const requires (CContiguousRange) { return Range::GetData(static_cast(*this)); } /** @return The reverse iterator to the first or end element. */ NODISCARD FORCEINLINE constexpr auto Begin() requires (CRange< T>) { return Range::Begin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto End() requires (CRange< T>) { return Range::End (static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange) { return Range::Begin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange) { return Range::End (static_cast(*this)); } /** @return The reverse iterator to the first or end element. */ NODISCARD FORCEINLINE constexpr auto RBegin() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::RBegin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto REnd() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::REnd (static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr auto RBegin() const requires (CBidirectionalRange && CCommonRange) { return Range::RBegin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr auto REnd() const requires (CBidirectionalRange && CCommonRange) { return Range::REnd (static_cast(*this)); } /** @return The number of elements in the container. */ NODISCARD FORCEINLINE constexpr size_t Num() requires (CSizedRange< T>) { return Range::Num(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { return Range::Num(static_cast(*this)); } /** @return true if the container is empty, false otherwise. */ NODISCARD FORCEINLINE constexpr bool IsEmpty() requires (CSizedRange< T> || CForwardRange< T>) { return Range::IsEmpty(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (CSizedRange || CForwardRange) { return Range::IsEmpty(static_cast(*this)); } /** @return true if the container is empty, false otherwise. */ NODISCARD FORCEINLINE constexpr explicit operator bool() requires (CSizedRange< T> || CForwardRange< T>) { return !Range::IsEmpty(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr explicit operator bool() const requires (CSizedRange || CForwardRange) { return !Range::IsEmpty(static_cast(*this)); } /** @return The reference to the requested element. */ NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) requires (CRandomAccessRange< T>) { return Range::Begin(static_cast< T&>(*this))[Index]; } NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) const requires (CRandomAccessRange) { return Range::Begin(static_cast(*this))[Index]; } /** @return The reference to the first or last element. */ NODISCARD FORCEINLINE constexpr decltype(auto) Front() requires (CForwardRange< T>) { return *Range::Begin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Front() const requires (CForwardRange) { return *Range::Begin(static_cast(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Back() requires (CBidirectionalRange< T> && CCommonRange< T>) { return *Range::RBegin(static_cast< T&>(*this)); } NODISCARD FORCEINLINE constexpr decltype(auto) Back() const requires (CBidirectionalRange && CCommonRange) { return *Range::RBegin(static_cast(*this)); } ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT private: FORCEINLINE constexpr TViewInterface() = default; FORCEINLINE constexpr TViewInterface(const TViewInterface&) = default; FORCEINLINE constexpr TViewInterface(TViewInterface&&) = default; FORCEINLINE constexpr TViewInterface& operator=(const TViewInterface&) = default; FORCEINLINE constexpr TViewInterface& operator=(TViewInterface&&) = default; FORCEINLINE constexpr ~TViewInterface() = default; friend T; }; NAMESPACE_END(Range) template requires (bEnableBorrowedRange) inline constexpr bool bEnableBorrowedRange> = true; template concept CView = CRange && CMovable && CDerivedFrom>>; 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)))); NAMESPACE_BEGIN(Range) /** A view type that produces a view of no elements of a particular type. */ template class TEmptyView : public TViewInterface> { public: using ElementType = T; using Reference = T&; using Iterator = T*; using Sentinel = T*; FORCEINLINE constexpr TEmptyView() = default; NODISCARD static FORCEINLINE constexpr Iterator Begin() { return nullptr; } NODISCARD static FORCEINLINE constexpr Sentinel End() { return nullptr; } NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; } NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; } NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; } }; static_assert(CContiguousRange>); static_assert( CCommonRange>); static_assert( CSizedRange>); static_assert( CView>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = true; NAMESPACE_BEGIN(Range) /** A view type that contains exactly one element of a specified value. */ template requires (CMoveConstructible) class TSingleView : public TViewInterface> { public: using ElementType = T; using Reference = T&; using ConstReference = const T&; using Iterator = T*; using ConstIterator = const T*; using Sentinel = T*; using ConstSentinel = const T*; FORCEINLINE constexpr TSingleView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr explicit TSingleView(const T& InValue) requires (CCopyConstructible) : Value(InValue) { } FORCEINLINE constexpr explicit TSingleView(T&& InValue) : Value(MoveTemp(InValue)) { } template requires (CConstructibleFrom) FORCEINLINE explicit TSingleView(FInPlace, Ts&&... Args) : Value(Forward(Args)...) { } FORCEINLINE constexpr Iterator Begin() { return GetData(); } FORCEINLINE constexpr ConstIterator Begin() const { return GetData(); } FORCEINLINE constexpr Sentinel End() { return GetData() + 1; } FORCEINLINE constexpr ConstSentinel End() const { return GetData() + 1; } NODISCARD FORCEINLINE constexpr T* GetData() { return AddressOf(Value); } NODISCARD FORCEINLINE constexpr const T* GetData() const { return AddressOf(Value); } NODISCARD static FORCEINLINE constexpr size_t Num() { return 1; } NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return false; } private: NO_UNIQUE_ADDRESS T Value; }; template TSingleView(T) -> TSingleView; static_assert(CContiguousRange>); static_assert( CCommonRange>); static_assert( CSizedRange>); static_assert( CView>); /** A view type that generates a sequence of elements by repeatedly incrementing an initial value. Can be either bounded or unbounded. */ template S = FUnreachableSentinel> requires (CSemiregular && CCopyable) class TIotaView : public TViewInterface> { private: class FSentinelImpl; public: using ElementType = W; using Reference = const W&; class Iterator; using Sentinel = TConditional, Iterator, FSentinelImpl>; FORCEINLINE constexpr TIotaView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr explicit TIotaView(W InValue) requires (CDefaultConstructible) : First(InValue), Last() { } FORCEINLINE constexpr explicit TIotaView(TIdentity InValue, TIdentity InLast) : First(InValue), Last(InLast) { } FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, Sentinel InLast) : First(InFirst.Value), Last(InLast.Value) { } FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, FUnreachableSentinel) requires (CSameAs) : First(InFirst.Value) { } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(First); } NODISCARD FORCEINLINE constexpr Sentinel End() const { return Sentinel(Last); } NODISCARD FORCEINLINE constexpr size_t Num() const requires ((CIntegral && CIntegral) || CSizedSentinelFor) { return Last - First; } NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return First == Last; } private: NO_UNIQUE_ADDRESS W First; NO_UNIQUE_ADDRESS S Last; public: class Iterator final { public: using ElementType = TRemoveCV; FORCEINLINE constexpr Iterator() requires (CDefaultConstructible) = default; NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) requires (CEqualityComparable) { return LHS.Value == RHS.Value; } NODISCARD FORCEINLINE constexpr W operator*() const { return Value; } NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Value); } FORCEINLINE constexpr Iterator& operator++() { ++Value; return *this; } FORCEINLINE constexpr Iterator operator++(int) { Iterator Temp = *this; ++Value; return Temp; } private: W Value; constexpr explicit Iterator(W InValue) : Value(InValue) { } friend FSentinelImpl; friend TIotaView; }; private: class FSentinelImpl final { public: FORCEINLINE constexpr FSentinelImpl() = default; NODISCARD FORCEINLINE constexpr bool operator==(const Iterator& InValue) const& { return Value == InValue.Value; } private: S Value; FORCEINLINE constexpr FSentinelImpl(S InValue) : Value(InValue) { } friend TIotaView; }; }; template TIotaView(T, U) -> TIotaView; static_assert(CForwardRange>); static_assert( CView>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = true; NAMESPACE_BEGIN(Range) /** A view type that generates a sequence of elements by repeatedly producing the same value. Can be either bounded or unbounded. */ template requires (CMoveConstructible && CSameAs>) class TRepeatView : public TViewInterface> { public: using ElementType = W; using Reference = const W&; class Iterator; using Sentinel = TConditional; FORCEINLINE constexpr TRepeatView() requires CDefaultConstructible = default; FORCEINLINE constexpr explicit TRepeatView(W InValue) requires (bIsUnreachable) : Value(MoveTemp(InValue)) { } FORCEINLINE constexpr explicit TRepeatView(W InValue, size_t InCount) requires (!bIsUnreachable) : Value(MoveTemp(InValue)), Count(InCount) { } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(*this, 0); } NODISCARD FORCEINLINE constexpr Sentinel End() const { if constexpr (bIsUnreachable) { return UnreachableSentinel; } else return Sentinel(*this, Count); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (!bIsUnreachable) { return Count; } private: using FSizeType = TConditional; NO_UNIQUE_ADDRESS W Value; NO_UNIQUE_ADDRESS FSizeType Count; public: class Iterator final { public: using ElementType = W; FORCEINLINE constexpr Iterator() requires (CDefaultConstructible) = default; NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) { return LHS.Current == RHS.Current; } NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const Iterator& LHS, const Iterator& RHS) { return LHS.Current <=> RHS.Current; } NODISCARD FORCEINLINE constexpr const W& operator*() const { return Owner->Value; } NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Owner->Value); } NODISCARD FORCEINLINE constexpr const W& operator[](ptrdiff Index) const { return *(*this + Index); } FORCEINLINE constexpr Iterator& operator++() { ++Current; return *this; } FORCEINLINE constexpr Iterator& operator--() { --Current; return *this; } FORCEINLINE constexpr Iterator operator++(int) { Iterator Temp = *this; --Current; return Temp; } FORCEINLINE constexpr Iterator operator--(int) { Iterator Temp = *this; ++Current; return Temp; } FORCEINLINE constexpr Iterator& operator+=(ptrdiff Offset) { Current -= Offset; return *this; } FORCEINLINE constexpr Iterator& operator-=(ptrdiff Offset) { Current += Offset; return *this; } NODISCARD friend FORCEINLINE constexpr Iterator operator+(Iterator Iter, ptrdiff Offset) { Iterator Temp = Iter; Temp -= Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr Iterator operator+(ptrdiff Offset, Iterator Iter) { Iterator Temp = Iter; Temp -= Offset; return Temp; } NODISCARD FORCEINLINE constexpr Iterator operator-(ptrdiff Offset) const { Iterator Temp = *this; Temp += Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const Iterator& LHS, const Iterator& RHS) { return RHS.Current - LHS.Current; } private: const TRepeatView* Owner; NO_UNIQUE_ADDRESS size_t Current; FORCEINLINE constexpr Iterator(const TRepeatView& InOwner, size_t InCurrent) : Owner(&InOwner), Current(InCurrent) { } friend TRepeatView; }; }; template TRepeatView(W) -> TRepeatView; template TRepeatView(W, size_t) -> TRepeatView; static_assert(CRandomAccessRange>); static_assert( CCommonRange>); static_assert( CSizedRange>); static_assert( CView>); NAMESPACE_END(Range) NAMESPACE_BEGIN(Range) /** A view of no elements of a particular type. */ template inline constexpr TEmptyView Empty; /** Creates a view that contains exactly one element of a specified value. */ template requires (CObject> && CMoveConstructible>) NODISCARD FORCEINLINE constexpr TSingleView> Single(T&& Value) { return TSingleView>(Forward(Value)); } /** Creates a view that generates a sequence of elements by repeatedly incrementing an initial value. */ template requires (CWeaklyIncrementable> && CCopyable>) NODISCARD FORCEINLINE constexpr TIotaView> Iota(W&& Value) { return TIotaView>(Forward(Value)); } /** Creates a view that generates a sequence of elements by repeatedly incrementing an initial value. */ template requires (CWeaklyIncrementable> && CWeaklyEqualityComparable && CCopyable> && CSemiregular>) NODISCARD FORCEINLINE constexpr TIotaView, TDecay> Iota(W&& Value, S&& Last) { return TIotaView, TDecay>(Forward(Value), Forward(Last)); } /** Creates a view that generates a sequence of elements by repeatedly producing the same value. */ template requires (CObject> && CMoveConstructible>) NODISCARD FORCEINLINE constexpr TRepeatView> Repeat(W&& Value) { return TRepeatView>(Forward(Value)); } /** Creates a view that generates a sequence of elements by repeatedly producing the same value. */ template requires (CObject> && CMoveConstructible>) NODISCARD FORCEINLINE constexpr TRepeatView, false> Repeat(W&& Value, size_t Count) { return TRepeatView, false>(Forward(Value), Count); } NAMESPACE_END(Range) NAMESPACE_BEGIN(Range) /** A view adapter that combines an iterator-sentinel pair. */ template S = I> class TRangeView : public TViewInterface> { public: using ElementType = TIteratorElementType; using Reference = TIteratorReferenceType; using Iterator = I; using Sentinel = S; FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr TRangeView(I InFirst, S InLast) : First(MoveTemp(InFirst)), Last(InLast) { } template requires (!CSameAs, TRangeView> && CConvertibleTo, I> && CConvertibleTo, S>) FORCEINLINE constexpr TRangeView(R&& InRange) : First(Range::Begin(Forward(InRange))), Last(Range::End(Forward(InRange))) { } NODISCARD FORCEINLINE constexpr I Begin() requires (!CCopyable) { return MoveTemp(First); } NODISCARD FORCEINLINE constexpr S End() requires (!CCopyable) { return MoveTemp(Last); } NODISCARD FORCEINLINE constexpr I Begin() const requires ( CCopyable) { return First; } NODISCARD FORCEINLINE constexpr S End() const requires ( CCopyable) { return Last; } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedSentinelFor) { return Last - First; } NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return First == Last; } private: NO_UNIQUE_ADDRESS I First; NO_UNIQUE_ADDRESS S Last; }; template S> TRangeView(I, S) -> TRangeView; template TRangeView(R&&) -> TRangeView, TRangeSentinelType>; NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = true; NAMESPACE_BEGIN(Range) /** A view adapter that references the elements of some other range. */ template requires (CObject) class TRefView : public TViewInterface> { public: using ElementType = TRangeElementType; using Reference = TRangeReferenceType; using Iterator = TRangeIteratorType; using Sentinel = TRangeSentinelType; template requires (!CSameAs, TRefView> && CConvertibleTo && CLValueReference) FORCEINLINE constexpr TRefView(T&& InRange) : Ptr(AddressOf(static_cast(Forward(InRange)))) { } NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Range::Begin(*Ptr); } NODISCARD FORCEINLINE constexpr Sentinel End() const { return Range::End (*Ptr); } NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange) { return Range::GetData(*Ptr); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { return Range::Num(*Ptr); } NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (requires(R* Ptr) { Range::IsEmpty(*Ptr); }) { return Range::IsEmpty(*Ptr); } NODISCARD FORCEINLINE constexpr R& GetBase() const { return *Ptr; } private: R* Ptr; }; template TRefView(R&) -> TRefView; static_assert(CContiguousRange>>); static_assert( CCommonRange>>); static_assert( CSizedRange>>); static_assert( CView>>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = true; NAMESPACE_BEGIN(Range) /** A view adapter that has unique ownership of a range. */ template requires (CMovable && !NAMESPACE_PRIVATE::TIsInitializerList::Value) class TOwningView : public TViewInterface> { public: using ElementType = TRangeElementType; using Reference = TRangeReferenceType; using Iterator = TRangeIteratorType; using Sentinel = TRangeSentinelType; FORCEINLINE constexpr TOwningView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr TOwningView(const TOwningView&) = delete; FORCEINLINE constexpr TOwningView(TOwningView&&) = default; FORCEINLINE constexpr TOwningView(R&& InRange) : Base(MoveTemp(InRange)) { } FORCEINLINE constexpr TOwningView& operator=(const TOwningView&) = delete; FORCEINLINE constexpr TOwningView& operator=(TOwningView&&) = default; NODISCARD FORCEINLINE constexpr Iterator Begin() { return Range::Begin(Base); } NODISCARD FORCEINLINE constexpr Sentinel End() { return Range::End (Base); } NODISCARD FORCEINLINE constexpr Iterator Begin() const requires (CRange) { return Range::Begin(Base); } NODISCARD FORCEINLINE constexpr Sentinel End() const requires (CRange) { return Range::End (Base); } NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< R>) { return Range::GetData(Base); } NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange) { return Range::GetData(Base); } NODISCARD FORCEINLINE constexpr size_t Num() requires (CSizedRange< R>) { return Range::Num(Base); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { return Range::Num(Base); } NODISCARD FORCEINLINE constexpr bool IsEmpty() requires (requires( R Base) { Range::IsEmpty(Base); }) { return Range::IsEmpty(Base); } NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (requires(const R Base) { Range::IsEmpty(Base); }) { return Range::IsEmpty(Base); } NODISCARD FORCEINLINE constexpr R& GetBase() & { return Base; } NODISCARD FORCEINLINE constexpr R&& GetBase() && { return MoveTemp(Base); } NODISCARD FORCEINLINE constexpr const R& GetBase() const& { return AsConst(Base); } NODISCARD FORCEINLINE constexpr const R&& GetBase() const&& { return MoveTemp(AsConst(Base)); } private: NO_UNIQUE_ADDRESS R Base; }; static_assert(CContiguousRange>>); static_assert( CCommonRange>>); static_assert( CSizedRange>>); static_assert( CView>>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = bEnableBorrowedRange; NAMESPACE_BEGIN(Range) /** A view adapter that includes all elements of a range. */ template using TAllView = TConditional>, TDecay, TConditional, TRefView>, TOwningView>>>; /** A view adapter that consists of the elements of a range that satisfies a predicate. */ template > Pred> requires (CView && CObject && CMoveConstructible) class TFilterView : public TViewInterface> { private: class FSentinelImpl; public: using ElementType = TRangeElementType; using Reference = TRangeReferenceType; class Iterator; using Sentinel = TConditional, Iterator, FSentinelImpl>; FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible && CDefaultConstructible) = default; FORCEINLINE constexpr explicit TFilterView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { } NODISCARD FORCEINLINE constexpr Iterator Begin() { Iterator Iter(*this, Range::Begin(Base)); do { if (Iter == End()) break; if (InvokeResult(GetPredicate(), *Iter)) break; ++Iter; } while (false); if constexpr (!CForwardRange) return MoveTemp(Iter); return Iter; } NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { return Base; } NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } NODISCARD FORCEINLINE constexpr const Pred& GetPredicate() const { return Predicate; } private: NO_UNIQUE_ADDRESS V Base; NO_UNIQUE_ADDRESS Pred Predicate; public: class Iterator final { public: using ElementType = TIteratorElementType>; FORCEINLINE constexpr Iterator() requires (CDefaultConstructible>) = default; NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) { return LHS.Current == RHS.Current; } NODISCARD FORCEINLINE constexpr TRangeReferenceType operator*() const { return *Current; } NODISCARD FORCEINLINE constexpr TRangeIteratorType operator->() const { return Current; } FORCEINLINE constexpr Iterator& operator++() { do ++Current; while (*this != Owner->End() && !InvokeResult(Owner->GetPredicate(), *Current)); return *this; } FORCEINLINE constexpr Iterator& operator--() requires (CBidirectionalIterator>) { do --Current; while (!InvokeResult(Owner->GetPredicate(), *Current)); return *this; } FORCEINLINE constexpr void operator++(int) { Current++; } FORCEINLINE constexpr Iterator operator++(int) requires (CForwardIterator>) { return Iterator(Owner, Current++); } FORCEINLINE constexpr Iterator operator--(int) requires (CBidirectionalIterator>) { return Iterator(Owner, Current--); } friend FORCEINLINE void IndirectlyCopy(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyCopyable , TRangeIteratorType>) { IndirectlyCopy(Iter.Current, Jter.Current); } friend FORCEINLINE void IndirectlyMove(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyMovable , TRangeIteratorType>) { IndirectlyMove(Iter.Current, Jter.Current); } friend FORCEINLINE void IndirectlySwap(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlySwappable, TRangeIteratorType>) { IndirectlySwap(Iter.Current, Jter.Current); } NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } private: TFilterView* Owner; NO_UNIQUE_ADDRESS TRangeIteratorType Current; FORCEINLINE constexpr Iterator(TFilterView& InOwner, TRangeIteratorType InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { } friend FSentinelImpl; friend TFilterView; }; private: class FSentinelImpl final { public: FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible>) = default; NODISCARD FORCEINLINE constexpr bool operator==(const Iterator& InValue) const& { return Current == InValue.Current; } NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } private: TRangeSentinelType Current; FORCEINLINE constexpr FSentinelImpl(TFilterView& InOwner, TRangeSentinelType InCurrent) : Current(InCurrent) { } friend TFilterView; }; }; template TFilterView(R&&, Pred) -> TFilterView, Pred>; static_assert(CBidirectionalRange, decltype([](auto) { return true; })>>); static_assert( CCommonRange, decltype([](auto) { return true; })>>); static_assert( CView, decltype([](auto) { return true; })>>); /** A view adapter of a sequence that applies a transformation function to each element. */ template requires (CView && CObject && CRegularInvocable> && CReferenceable>>) class TTransformView : public TViewInterface> { private: template class FIteratorImpl; template class FSentinelImpl; public: using ElementType = TRemoveReference>>; FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible&& CDefaultConstructible) = default; FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { } NODISCARD FORCEINLINE constexpr FIteratorImpl Begin() { return FIteratorImpl(*this, Range::Begin(Base)); } NODISCARD FORCEINLINE constexpr FIteratorImpl Begin() const requires (CRange && CRegularInvocable>) { return FIteratorImpl(*this, Range::Begin(Base)); } NODISCARD FORCEINLINE constexpr FSentinelImpl End() { return FSentinelImpl(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr FIteratorImpl End() requires (CCommonRange) { return FIteratorImpl(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr FSentinelImpl End() const requires (CRange && CRegularInvocable>) { return FSentinelImpl(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr FIteratorImpl End() const requires (CCommonRange && CRegularInvocable>) { return FIteratorImpl(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr size_t Num() requires CSizedRange< V> { return Range::Num(Base); } NODISCARD FORCEINLINE constexpr size_t Num() const requires CSizedRange { return Range::Num(Base); } NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { return Base; } NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } private: NO_UNIQUE_ADDRESS V Base; NO_UNIQUE_ADDRESS F Func; template class FIteratorImpl { private: using FOwner = TConditional; using FBase = TConditional; using FFunc = TConditional; public: using ElementType = TRemoveCVRef>>; FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible>) = default; FORCEINLINE constexpr FIteratorImpl(FIteratorImpl Iter) requires (bConst && CConvertibleTo, TRangeIteratorType>) : Owner(Iter.Owner), Current(MoveTemp(Iter.Current)) { } NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSentinelFor, TRangeIteratorType>) { return LHS.Current == RHS.Current; } NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSizedSentinelFor, TRangeIteratorType>) { return LHS.Current <=> RHS.Current; } NODISCARD FORCEINLINE constexpr decltype(auto) operator*() const { return Invoke(Owner->Func, *Current); } NODISCARD FORCEINLINE constexpr decltype(auto) operator[](ptrdiff Index) const requires (CRandomAccessRange) { return Invoke(Owner->Func, Current[Index]); } FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; } FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange) { --Current; return *this; } FORCEINLINE constexpr void operator++(int) { Current++; } FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange) { return FIteratorImpl(Current++); } FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange) { return FIteratorImpl(Current--); } FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) requires (CRandomAccessRange) { Current += Offset; return *this; } FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) requires (CRandomAccessRange) { Current -= Offset; return *this; } NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(FIteratorImpl Iter, ptrdiff Offset) requires (CRandomAccessRange) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, FIteratorImpl Iter) requires (CRandomAccessRange) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; } NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const requires (CRandomAccessRange) { FIteratorImpl Temp = *this; Temp -= Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSizedSentinelFor, TRangeIteratorType>) { return LHS.Current - RHS.Current; } NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } private: NO_UNIQUE_ADDRESS FOwner* Owner; NO_UNIQUE_ADDRESS TRangeIteratorType Current; FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIteratorType InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { } template friend class FIteratorImpl; template friend class FSentinelImpl; friend TTransformView; }; template class FSentinelImpl { private: using FOwner = TConditional; using FBase = TConditional; public: FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible>) = default; FORCEINLINE constexpr FSentinelImpl(FSentinelImpl Sentinel) requires (bConst && CConvertibleTo, TRangeSentinelType>) : Current(Sentinel.Current) { } NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Current == InValue.Current; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FSentinelImpl& RHS) requires CSizedSentinelFor, TRangeIteratorType> { return LHS.Current - RHS.Current; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl& RHS) requires CSizedSentinelFor, TRangeIteratorType> { return RHS.Current - LHS.Current; } NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } private: NO_UNIQUE_ADDRESS TRangeSentinelType Current; FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinelType InCurrent) : Current(InCurrent) { } friend TTransformView; }; }; template TTransformView(R&&, F) -> TTransformView, F>; static_assert(CRandomAccessRange, decltype([](auto) { return 0; })>>); static_assert( CCommonRange, decltype([](auto) { return 0; })>>); static_assert( CSizedRange, decltype([](auto) { return 0; })>>); static_assert( CView, decltype([](auto) { return 0; })>>); NAMESPACE_END(Range) NAMESPACE_BEGIN(Range) /** Creates A view adapter that combines an iterator-sentinel pair. */ template S = I> NODISCARD FORCEINLINE constexpr TRangeView View(I First, S Last) { return TRangeView(MoveTemp(First), MoveTemp(Last)); } /** Creates A view adapter that includes all elements of a range. */ template NODISCARD FORCEINLINE constexpr TAllView All(R&& InRange) { return TAllView(Forward(InRange)); } /** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */ template requires (requires { TFilterView(DeclVal(), DeclVal()); }) NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate) { return TFilterView(Forward(Base), Forward(Predicate)); } /** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */ template NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate) { return [&Predicate](R&& Base) requires (requires { TFilterView(DeclVal(), DeclVal()); }) { return TFilterView(Forward(Base), Forward(Predicate)); }; } /** Creates A view adapter of a sequence that applies a transformation function to each element. */ template requires (requires { TTransformView(DeclVal(), DeclVal()); }) NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func) { return TTransformView(Forward(Base), Forward(Func)); } /** Creates A view adapter of a sequence that applies a transformation function to each element. */ template NODISCARD FORCEINLINE constexpr auto Transform(F&& Func) { return [&Func](R&& Base) requires (requires { TTransformView(DeclVal(), DeclVal()); }) { return TTransformView(Forward(Base), Forward(Func)); }; } NAMESPACE_END(Range) template requires (CRange>) NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& View) { return Invoke(Forward(View), Forward(Range)); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END