#pragma once #include "CoreTypes.h" #include "Ranges/View.h" #include "Ranges/Pipe.h" #include "Ranges/Utility.h" #include "Ranges/AllView.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Range) /** * A view adapter of a sequence that applies a transformation function to each element. * When based on an input view, the transform view satisfies at least an input view up to a random access view. * When based on a common view, the transform view satisfies a common view. When based on a sized view, * the transform view satisfies a sized view. When based on a forward view and the function return * an assignable value, the transform view satisfies an output view. */ template requires (CView && CObject && CRegularInvocable> && CReferenceable>>) class TTransformView : public IBasicViewInterface> { private: template class FIteratorImpl; template class FSentinelImpl; public: FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible&& CDefaultConstructible) = default; FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { } NODISCARD FORCEINLINE constexpr auto Begin() { return FIteratorImpl(*this, Range::Begin(Base)); } NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange && CRegularInvocable>) { return FIteratorImpl(*this, Range::Begin(Base)); } NODISCARD FORCEINLINE constexpr auto End() { if constexpr (CCommonRange) { return FIteratorImpl(*this, Range::End(Base)); } else return FSentinelImpl(*this, Range::End(Base)); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange && CRegularInvocable>) { if constexpr (CCommonRange) { return FIteratorImpl(*this, Range::End(Base)); } else return FSentinelImpl(*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 FElementType = TRemoveCVRef>>; FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible>) = default; FORCEINLINE constexpr FIteratorImpl(FIteratorImpl Iter) requires (bConst && CConvertibleTo, TRangeIterator>) : Owner(Iter.Owner), Current(MoveTemp(Iter).GetBase()) { } NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable>) { return LHS.GetBase() == RHS.GetBase(); } NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CThreeWayComparable>) { return LHS.GetBase() <=> RHS.GetBase(); } NODISCARD FORCEINLINE constexpr decltype(auto) operator*() const { return Invoke(Owner->Func, *GetBase()); } NODISCARD FORCEINLINE constexpr decltype(auto) operator[](ptrdiff Index) const requires (CRandomAccessRange) { return Invoke(Owner->Func, GetBase()[Index]); } FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; } FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange) { --Current; return *this; } FORCEINLINE constexpr void operator++(int) { ++*this; } FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange) { FIteratorImpl Temp = *this; ++*this; return Temp; } FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange) { FIteratorImpl Temp = *this; --*this; return Temp; } 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 FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset) const requires (CRandomAccessRange) { FIteratorImpl Temp = *this; 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 FIteratorImpl operator+(ptrdiff Offset, const FIteratorImpl& Iter) requires (CRandomAccessRange) { return Iter + Offset; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSizedSentinelFor, TRangeIterator>) { return LHS.GetBase() - RHS.GetBase(); } NODISCARD FORCEINLINE constexpr const TRangeIterator& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr TRangeIterator GetBase() && { return MoveTemp(Current); } private: NO_UNIQUE_ADDRESS FOwner* Owner; NO_UNIQUE_ADDRESS TRangeIterator Current; FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIterator 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, TRangeSentinel>) : Current(Sentinel.GetBase()) { } NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Current == InValue.GetBase(); } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FSentinelImpl& RHS) requires CSizedSentinelFor, TRangeIterator> { return LHS.GetBase() - RHS.GetBase(); } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl& RHS) requires CSizedSentinelFor, TRangeIterator> { return LHS.GetBase() - RHS.GetBase(); } NODISCARD FORCEINLINE constexpr TRangeSentinel GetBase() const { return Current; } private: NO_UNIQUE_ADDRESS TRangeSentinel Current; FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinel InCurrent) : Current(InCurrent) { } friend TTransformView; }; }; template TTransformView(R&&, F) -> TTransformView, F>; static_assert( CInputRange>>, int(*)(int)>>); static_assert( CForwardRange>>, int(*)(int)>>); static_assert(CBidirectionalRange>>, int(*)(int)>>); static_assert( CRandomAccessRange>>, int(*)(int)>>); static_assert( CRandomAccessRange>>, int(*)(int)>>); static_assert(CCommonRange>>, int(*)(int)>>); static_assert( CSizedRange>>, int(*)(int)>>); static_assert( CView>>, int(*)(int)>>); static_assert(COutputRange>>, int&(*)(int)>, int>); NAMESPACE_END(Range) NAMESPACE_BEGIN(Range) /** 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) { using FClosure = decltype([] requires (requires { Range::Transform(DeclVal(), DeclVal()); }) (R&& Base, T&& Func) { return Range::Transform(Forward(Base), Forward(Func)); }); return TAdaptorClosure>(Forward(Func)); } NAMESPACE_END(Range) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END