#pragma once #include "CoreTypes.h" #include "TypeTraits/TypeTraits.h" #include "Templates/Utility.h" #include "Iterators/Utility.h" #include "Iterators/BasicIterator.h" #include "Iterators/CountedIterator.h" #include "Numerics/Math.h" #include "Ranges/Utility.h" #include "Ranges/Pipe.h" #include "Ranges/View.h" #include "Ranges/AllView.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Range) /** * A view adapter that includes a specified number of elements from the beginning of a range. * When based on any view, the take view satisfies the corresponding any view. * When based on a random access and sized view, the take view satisfies a common view. */ template class TTakeView : public IBasicViewInterface> { private: template class FSentinelImpl; public: FORCEINLINE constexpr TTakeView() requires (CDefaultConstructible) = default; FORCEINLINE constexpr TTakeView(V InBase, size_t InCount) : Base(MoveTemp(InBase)), Count(InCount) { } NODISCARD FORCEINLINE constexpr auto Begin() requires (!CSimpleView) { if constexpr (CSizedRange) { if constexpr (CRandomAccessRange) { return Range::Begin(Base); } else return MakeCountedIterator(Range::Begin(Base), Num()); } else return MakeCountedIterator(Range::Begin(Base), Count); } NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange) { if constexpr (CSizedRange) { if constexpr (CRandomAccessRange) { return Range::Begin(Base); } else return MakeCountedIterator(Range::Begin(Base), Num()); } else return MakeCountedIterator(Range::Begin(Base), Count); } NODISCARD FORCEINLINE constexpr auto End() requires (!CSimpleView) { if constexpr (CSizedRange) { if constexpr (CRandomAccessRange) { return Range::Begin(Base) + Num(); } else return DefaultSentinel; } else return FSentinelImpl(Range::End(Base)); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange) { if constexpr (CSizedRange) { if constexpr (CRandomAccessRange) { return Range::Begin(Base) + Num(); } else return DefaultSentinel; } else return FSentinelImpl(Range::End(Base)); } NODISCARD FORCEINLINE constexpr size_t Num() requires (CSizedRange< V>) { return Math::Min(Range::Num(Base), Count); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { return Math::Min(Range::Num(Base), Count); } NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { return Base; } NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } private: NO_UNIQUE_ADDRESS V Base; size_t Count; template class FSentinelImpl final { private: using FBase = TConditional; public: FORCEINLINE constexpr FSentinelImpl() = default; FORCEINLINE constexpr FSentinelImpl(FSentinelImpl Sentinel) requires (bConst && CConvertibleTo, TRangeSentinel>) : Current(Sentinel.Current) { } NODISCARD FORCEINLINE constexpr bool operator==(const TCountedIterator>& InValue) const& { return InValue.Num() == 0 || InValue.GetBase() == Current; } template requires (CSentinelFor, TRangeIterator>>) NODISCARD FORCEINLINE constexpr bool operator==(const TCountedIterator>>& InValue) { return InValue.Num() == 0 || InValue.GetBase() == Current; } NODISCARD FORCEINLINE constexpr TRangeSentinel GetBase() const { return Current; } private: NO_UNIQUE_ADDRESS TRangeSentinel Current; FORCEINLINE constexpr FSentinelImpl(TRangeSentinel InCurrent) : Current(InCurrent) { } friend TTakeView; }; }; template TTakeView(R&&, size_t) -> TTakeView>; static_assert( CInputRange>>>>); static_assert( CForwardRange>>>>); static_assert(CBidirectionalRange>>>>); static_assert( CRandomAccessRange>>>>); static_assert( CContiguousRange>>>>); static_assert(CCommonRange>>>>); static_assert( CSizedRange>>>>); static_assert( CView>>>>); static_assert(COutputRange>>>, int>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = bEnableBorrowedRange; NAMESPACE_BEGIN(Range) /** Creates A view adapter that includes a specified number of elements from the beginning of a range. */ template requires (requires { TTakeView(DeclVal(), DeclVal()); }) NODISCARD FORCEINLINE constexpr auto Take(R&& Base, size_t Count) { return TTakeView(Forward(Base), Count); } /** Creates A view adapter that includes a specified number of elements from the beginning of a range. */ NODISCARD FORCEINLINE constexpr auto Take(size_t Count) { using FClosure = decltype([] requires (requires { Range::Take(DeclVal(), DeclVal()); }) (R&& Base, size_t Count) { return Range::Take(Forward(Base), Count); }); return TAdaptorClosure(Count); } NAMESPACE_END(Range) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END