feat(range): add TTakeWhileView adapter
This commit is contained in:
parent
e6d525f2c3
commit
f88cf7ef3e
@ -11,3 +11,4 @@
|
|||||||
#include "Range/FilterView.h"
|
#include "Range/FilterView.h"
|
||||||
#include "Range/TransformView.h"
|
#include "Range/TransformView.h"
|
||||||
#include "Range/TakeView.h"
|
#include "Range/TakeView.h"
|
||||||
|
#include "Range/TakeWhileView.h"
|
||||||
|
149
Redcraft.Utility/Source/Public/Range/TakeWhileView.h
Normal file
149
Redcraft.Utility/Source/Public/Range/TakeWhileView.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreTypes.h"
|
||||||
|
#include "TypeTraits/TypeTraits.h"
|
||||||
|
#include "Templates/Utility.h"
|
||||||
|
#include "Iterator/Utility.h"
|
||||||
|
#include "Iterator/BasicIterator.h"
|
||||||
|
#include "Iterator/CountedIterator.h"
|
||||||
|
#include "Numeric/Math.h"
|
||||||
|
#include "Range/Utility.h"
|
||||||
|
#include "Range/Pipe.h"
|
||||||
|
#include "Range/View.h"
|
||||||
|
#include "Range/AllView.h"
|
||||||
|
|
||||||
|
NAMESPACE_REDCRAFT_BEGIN
|
||||||
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
NAMESPACE_BEGIN(Range)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <CInputRange V, CPredicate<TRangeReference<V>> Pred> requires (CView<V> && CObject<Pred> && CMoveConstructible<Pred>)
|
||||||
|
class TTakeWhileView : public IBasicViewInterface<TTakeWhileView<V, Pred>>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
template <bool bConst> class FSentinelImpl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using FElementType = TRangeElement<V>;
|
||||||
|
using FReference = TRangeReference<V>;
|
||||||
|
|
||||||
|
FORCEINLINE constexpr TTakeWhileView() requires (CDefaultConstructible<V>&& CDefaultConstructible<Pred>) = default;
|
||||||
|
|
||||||
|
FORCEINLINE constexpr explicit TTakeWhileView(V InBase, Pred InPredicate) : Base(MoveTemp(InBase)), Predicate(MoveTemp(InPredicate)) { }
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr auto Begin() requires (!CSimpleView<V>)
|
||||||
|
{
|
||||||
|
return Range::Begin(Base);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange<const V> && CPredicate<const Pred&, TRangeReference<const V>>)
|
||||||
|
{
|
||||||
|
return Range::Begin(Base);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr auto End() requires (!CSimpleView<V>)
|
||||||
|
{
|
||||||
|
return FSentinelImpl<false>(Range::End(Base), AddressOf(Predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr auto End() const requires (CRange<const V> && CPredicate<const Pred&, TRangeReference<const V>>)
|
||||||
|
{
|
||||||
|
return FSentinelImpl<true>(Range::End(Base), AddressOf(Predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { 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 <bool bConst>
|
||||||
|
class FSentinelImpl final
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
using FBase = TConditional<bConst, const V, V>;
|
||||||
|
using FPred = TConditional<bConst, const Pred, Pred>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FORCEINLINE constexpr FSentinelImpl() = default;
|
||||||
|
|
||||||
|
FORCEINLINE constexpr FSentinelImpl(FSentinelImpl<!bConst> Sentinel) requires (bConst && CConvertibleTo<TRangeSentinel<V>, TRangeSentinel<FBase>>)
|
||||||
|
: Current(Sentinel.Current), Predicate(Sentinel.Predicate)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr bool operator==(const TRangeIterator<FBase>& InValue) const&
|
||||||
|
{
|
||||||
|
return InValue == Current || !InvokeResult<bool>(*Predicate, *InValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODISCARD FORCEINLINE constexpr TRangeSentinel<FBase> GetBase() const { return Current; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
NO_UNIQUE_ADDRESS TRangeSentinel<FBase> Current;
|
||||||
|
|
||||||
|
FPred* Predicate;
|
||||||
|
|
||||||
|
FORCEINLINE constexpr FSentinelImpl(TRangeSentinel<FBase> InCurrent, FPred* InPredicate) : Current(InCurrent), Predicate(InPredicate) { }
|
||||||
|
|
||||||
|
friend TTakeWhileView;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename Pred>
|
||||||
|
TTakeWhileView(R&&, Pred) -> TTakeWhileView<TAllView<R>, Pred>;
|
||||||
|
|
||||||
|
static_assert( CInputRange<TTakeWhileView<TAllView<IRange< IInputIterator<int&>>>, bool(*)(int)>>);
|
||||||
|
static_assert( CForwardRange<TTakeWhileView<TAllView<IRange< IForwardIterator<int&>>>, bool(*)(int)>>);
|
||||||
|
static_assert(CBidirectionalRange<TTakeWhileView<TAllView<IRange<IBidirectionalIterator<int&>>>, bool(*)(int)>>);
|
||||||
|
static_assert( CRandomAccessRange<TTakeWhileView<TAllView<IRange< IRandomAccessIterator<int&>>>, bool(*)(int)>>);
|
||||||
|
static_assert( CContiguousRange<TTakeWhileView<TAllView<IRange< IContiguousIterator<int&>>>, bool(*)(int)>>);
|
||||||
|
|
||||||
|
static_assert(CView<TTakeWhileView<TAllView<IRange<IInputIterator<int>>>, bool(*)(int)>>);
|
||||||
|
|
||||||
|
static_assert(COutputRange<TTakeWhileView<TAllView<IRange<IForwardIterator<int&>>>, bool(*)(int)>, int>);
|
||||||
|
|
||||||
|
NAMESPACE_END(Range)
|
||||||
|
|
||||||
|
NAMESPACE_BEGIN(Range)
|
||||||
|
|
||||||
|
/** Creates A view adapter that includes elements that satisfy the predicate from the beginning of the range. */
|
||||||
|
template <CViewableRange R, typename Pred> requires (requires { TTakeWhileView(DeclVal<R>(), DeclVal<Pred>()); })
|
||||||
|
NODISCARD FORCEINLINE constexpr auto TakeWhile(R&& Base, Pred&& Predicate)
|
||||||
|
{
|
||||||
|
return TTakeWhileView(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates A view adapter that includes elements that satisfy the predicate from the beginning of the range. */
|
||||||
|
template <typename Pred>
|
||||||
|
NODISCARD FORCEINLINE constexpr auto TakeWhile(Pred&& Predicate)
|
||||||
|
{
|
||||||
|
using FClosure = decltype([]<CViewableRange R, typename T> requires (requires { Range::TakeWhile(DeclVal<R>(), DeclVal<T>()); }) (R&& Base, T&& Predicate)
|
||||||
|
{
|
||||||
|
return Range::TakeWhile(Forward<R>(Base), Forward<T>(Predicate));
|
||||||
|
});
|
||||||
|
|
||||||
|
return TAdaptorClosure<FClosure, TDecay<Pred>>(Forward<Pred>(Predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
NAMESPACE_END(Range)
|
||||||
|
|
||||||
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
NAMESPACE_REDCRAFT_END
|
Loading…
Reference in New Issue
Block a user