#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(Ranges) /** * A view adapter that includes elements that satisfy the predicate from the beginning of the range. * When based on an input view, the take while view satisfies at least an input view up to a contiguous view. * When based on a forward and output view, the take while view satisfies an output view. */ template > Pred> requires (CView && CObject && CMoveConstructible) class TTakeWhileView : public IBasicViewInterface> { private: template class FSentinelImpl; public: using FElementType = TRangeElement; using FReference = TRangeReference; FORCEINLINE constexpr TTakeWhileView() requires (CDefaultConstructible&& CDefaultConstructible) = default; FORCEINLINE constexpr explicit TTakeWhileView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { } NODISCARD FORCEINLINE constexpr auto Begin() requires (!CSimpleView) { return Ranges::Begin(Base); } NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange && CPredicate>) { return Ranges::Begin(Base); } NODISCARD FORCEINLINE constexpr auto End() requires (!CSimpleView) { return FSentinelImpl(Ranges::End(Base), AddressOf(Predicate)); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange && CPredicate>) { return FSentinelImpl(Ranges::End(Base), AddressOf(Predicate)); } 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; template class FSentinelImpl final { private: using FBase = TConditional; using FPred = TConditional; public: FORCEINLINE constexpr FSentinelImpl() = default; FORCEINLINE constexpr FSentinelImpl(FSentinelImpl Sentinel) requires (bConst && CConvertibleTo, TRangeSentinel>) : Current(Sentinel.Current), Predicate(Sentinel.Predicate) { } NODISCARD FORCEINLINE constexpr bool operator==(const TRangeIterator& InValue) const& { return InValue == Current || !InvokeResult(*Predicate, *InValue); } NODISCARD FORCEINLINE constexpr TRangeSentinel GetBase() const { return Current; } private: NO_UNIQUE_ADDRESS TRangeSentinel Current; FPred* Predicate; FORCEINLINE constexpr FSentinelImpl(TRangeSentinel InCurrent, FPred* InPredicate) : Current(InCurrent), Predicate(InPredicate) { } friend TTakeWhileView; }; }; template TTakeWhileView(R&&, Pred) -> TTakeWhileView, Pred>; static_assert( CInputRange>>, bool(*)(int)>>); static_assert( CForwardRange>>, bool(*)(int)>>); static_assert(CBidirectionalRange>>, bool(*)(int)>>); static_assert( CRandomAccessRange>>, bool(*)(int)>>); static_assert( CContiguousRange>>, bool(*)(int)>>); static_assert(CView>>, bool(*)(int)>>); static_assert(COutputRange>>, bool(*)(int)>, int>); NAMESPACE_END(Ranges) NAMESPACE_BEGIN(Ranges) /** Creates A view adapter that includes elements that satisfy the predicate from the beginning of the range. */ template requires (requires { TTakeWhileView(DeclVal(), DeclVal()); }) NODISCARD FORCEINLINE constexpr auto TakeWhile(R&& Base, Pred&& Predicate) { return TTakeWhileView(Forward(Base), Forward(Predicate)); } /** Creates A view adapter that includes elements that satisfy the predicate from the beginning of the range. */ template NODISCARD FORCEINLINE constexpr auto TakeWhile(Pred&& Predicate) { using FClosure = decltype([] requires (requires { Ranges::TakeWhile(DeclVal(), DeclVal()); }) (R&& Base, T&& Predicate) { return Ranges::TakeWhile(Forward(Base), Forward(Predicate)); }); return TAdaptorClosure>(Forward(Predicate)); } NAMESPACE_END(Ranges) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END