#pragma once #include "CoreTypes.h" #include "Range/Range.h" #include "Memory/Address.h" #include "Numeric/Numeric.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) template using TRangeIteratorType = TRangeIterator; template using TRangeSentinelType = TRangeSentinel; template using TRangeElementType = TRangeElement; template using TRangeReferenceType = TRangeReference; template using TRangeRValueReferenceType = TRangeRValueReference; NAMESPACE_BEGIN(Range) /** A view adapter that references the elements of some other range. */ template requires (CObject) class TRefView : public IBasicViewInterface> { 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 IBasicViewInterface> { 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 IBasicViewInterface> { 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 IBasicViewInterface> { 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 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