refactor(range): split the remaining range library into multiple files
This commit is contained in:
parent
dca4eaa6eb
commit
d88eb4be5e
@ -1,527 +0,0 @@
|
||||
#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 <typename R>
|
||||
using TRangeIteratorType = TRangeIterator<R>;
|
||||
|
||||
template <typename R>
|
||||
using TRangeSentinelType = TRangeSentinel<R>;
|
||||
|
||||
template <typename R>
|
||||
using TRangeElementType = TRangeElement<R>;
|
||||
|
||||
template <typename R>
|
||||
using TRangeReferenceType = TRangeReference<R>;
|
||||
|
||||
template <typename R>
|
||||
using TRangeRValueReferenceType = TRangeRValueReference<R>;
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** A view adapter that references the elements of some other range. */
|
||||
template <CRange R> requires (CObject<R>)
|
||||
class TRefView : public IBasicViewInterface<TRefView<R>>
|
||||
{
|
||||
public:
|
||||
|
||||
using ElementType = TRangeElementType<R>;
|
||||
using Reference = TRangeReferenceType<R>;
|
||||
using Iterator = TRangeIteratorType<R>;
|
||||
using Sentinel = TRangeSentinelType<R>;
|
||||
|
||||
template <typename T> requires (!CSameAs<TRemoveCVRef<T>, TRefView> && CConvertibleTo<T, R&> && CLValueReference<T>)
|
||||
FORCEINLINE constexpr TRefView(T&& InRange) : Ptr(AddressOf(static_cast<R&>(Forward<T>(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<R>) { return Range::GetData(*Ptr); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange<R>) { 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 <typename R>
|
||||
TRefView(R&) -> TRefView<R>;
|
||||
|
||||
static_assert(CContiguousRange<TRefView<TSingleView<int>>>);
|
||||
static_assert( CCommonRange<TRefView<TSingleView<int>>>);
|
||||
static_assert( CSizedRange<TRefView<TSingleView<int>>>);
|
||||
static_assert( CView<TRefView<TSingleView<int>>>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
template <typename T>
|
||||
constexpr bool bEnableBorrowedRange<Range::TRefView<T>> = true;
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** A view adapter that has unique ownership of a range. */
|
||||
template <CRange R> requires (CMovable<R> && !NAMESPACE_PRIVATE::TIsInitializerList<R>::Value)
|
||||
class TOwningView : public IBasicViewInterface<TOwningView<R>>
|
||||
{
|
||||
public:
|
||||
|
||||
using ElementType = TRangeElementType<R>;
|
||||
using Reference = TRangeReferenceType<R>;
|
||||
using Iterator = TRangeIteratorType<R>;
|
||||
using Sentinel = TRangeSentinelType<R>;
|
||||
|
||||
FORCEINLINE constexpr TOwningView() requires (CDefaultConstructible<R>) = 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<const R>) { return Range::Begin(Base); }
|
||||
NODISCARD FORCEINLINE constexpr Sentinel End() const requires (CRange<const R>) { return Range::End (Base); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< R>) { return Range::GetData(Base); }
|
||||
NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange<const R>) { 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<const R>) { 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<TOwningView<TSingleView<int>>>);
|
||||
static_assert( CCommonRange<TOwningView<TSingleView<int>>>);
|
||||
static_assert( CSizedRange<TOwningView<TSingleView<int>>>);
|
||||
static_assert( CView<TOwningView<TSingleView<int>>>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
template <typename T>
|
||||
constexpr bool bEnableBorrowedRange<Range::TOwningView<T>> = bEnableBorrowedRange<T>;
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** A view adapter that includes all elements of a range. */
|
||||
template <CViewableRange R>
|
||||
using TAllView =
|
||||
TConditional<CView<TDecay<R>>, TDecay<R>,
|
||||
TConditional<CLValueReference<R>, TRefView<TRemoveReference<R>>, TOwningView<TRemoveReference<R>>>>;
|
||||
|
||||
/** A view adapter that consists of the elements of a range that satisfies a predicate. */
|
||||
template <CInputRange V, CPredicate<TRangeReferenceType<V>> Pred> requires (CView<V> && CObject<Pred> && CMoveConstructible<Pred>)
|
||||
class TFilterView : public IBasicViewInterface<TFilterView<V, Pred>>
|
||||
{
|
||||
private:
|
||||
|
||||
class FSentinelImpl;
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TRangeElementType<V>;
|
||||
|
||||
using Reference = TRangeReferenceType<V>;
|
||||
|
||||
class Iterator;
|
||||
|
||||
using Sentinel = TConditional<CCommonRange<V>, Iterator, FSentinelImpl>;
|
||||
|
||||
FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = 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<bool>(GetPredicate(), *Iter)) break;
|
||||
|
||||
++Iter;
|
||||
}
|
||||
while (false);
|
||||
|
||||
if constexpr (!CForwardRange<V>) return MoveTemp(Iter);
|
||||
|
||||
return Iter;
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); }
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
|
||||
class Iterator final
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TIteratorElementType<TRangeIteratorType<V>>;
|
||||
|
||||
FORCEINLINE constexpr Iterator() requires (CDefaultConstructible<TRangeIteratorType<V>>) = default;
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS)
|
||||
{
|
||||
return LHS.Current == RHS.Current;
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TRangeReferenceType<V> operator*() const { return *Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIteratorType<V> operator->() const { return Current; }
|
||||
|
||||
FORCEINLINE constexpr Iterator& operator++()
|
||||
{
|
||||
do ++Current; while (*this != Owner->End() && !InvokeResult<bool>(Owner->GetPredicate(), *Current));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr Iterator& operator--() requires (CBidirectionalIterator<TRangeIteratorType<V>>)
|
||||
{
|
||||
do --Current; while (!InvokeResult<bool>(Owner->GetPredicate(), *Current));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr void operator++(int) { Current++; }
|
||||
FORCEINLINE constexpr Iterator operator++(int) requires (CForwardIterator<TRangeIteratorType<V>>) { return Iterator(Owner, Current++); }
|
||||
FORCEINLINE constexpr Iterator operator--(int) requires (CBidirectionalIterator<TRangeIteratorType<V>>) { return Iterator(Owner, Current--); }
|
||||
|
||||
friend FORCEINLINE void IndirectlyCopy(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyCopyable <TRangeIteratorType<V>, TRangeIteratorType<V>>) { IndirectlyCopy(Iter.Current, Jter.Current); }
|
||||
friend FORCEINLINE void IndirectlyMove(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyMovable <TRangeIteratorType<V>, TRangeIteratorType<V>>) { IndirectlyMove(Iter.Current, Jter.Current); }
|
||||
friend FORCEINLINE void IndirectlySwap(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlySwappable<TRangeIteratorType<V>, TRangeIteratorType<V>>) { IndirectlySwap(Iter.Current, Jter.Current); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIteratorType<V>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIteratorType<V> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
TFilterView* Owner;
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeIteratorType<V> Current;
|
||||
|
||||
FORCEINLINE constexpr Iterator(TFilterView& InOwner, TRangeIteratorType<V> InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { }
|
||||
|
||||
friend FSentinelImpl;
|
||||
|
||||
friend TFilterView;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
class FSentinelImpl final
|
||||
{
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible<TRangeSentinelType<V>>) = default;
|
||||
|
||||
NODISCARD FORCEINLINE constexpr bool operator==(const Iterator& InValue) const& { return Current == InValue.Current; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIteratorType<V>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIteratorType<V> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
TRangeSentinelType<V> Current;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(TFilterView& InOwner, TRangeSentinelType<V> InCurrent) : Current(InCurrent) { }
|
||||
|
||||
friend TFilterView;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename Pred>
|
||||
TFilterView(R&&, Pred) -> TFilterView<TAllView<R>, Pred>;
|
||||
|
||||
static_assert(CBidirectionalRange<TFilterView<TSingleView<int>, decltype([](auto) { return true; })>>);
|
||||
static_assert( CCommonRange<TFilterView<TSingleView<int>, decltype([](auto) { return true; })>>);
|
||||
static_assert( CView<TFilterView<TSingleView<int>, decltype([](auto) { return true; })>>);
|
||||
|
||||
/** A view adapter of a sequence that applies a transformation function to each element. */
|
||||
template <CInputRange V, CMoveConstructible F> requires (CView<V> && CObject<F>
|
||||
&& CRegularInvocable<F&, TRangeReferenceType<V>> && CReferenceable<TInvokeResult<F&, TRangeReferenceType<V>>>)
|
||||
class TTransformView : public IBasicViewInterface<TTransformView<V, F>>
|
||||
{
|
||||
private:
|
||||
|
||||
template <bool bConst> class FIteratorImpl;
|
||||
template <bool bConst> class FSentinelImpl;
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TRemoveReference<TInvokeResult<F&, TRangeReferenceType<V>>>;
|
||||
|
||||
FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible<V>&& CDefaultConstructible<F>) = default;
|
||||
|
||||
FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl<false> Begin()
|
||||
{
|
||||
return FIteratorImpl<false>(*this, Range::Begin(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl<true> Begin() const
|
||||
requires (CRange<const V> && CRegularInvocable<const F&, TRangeReferenceType<const V>>)
|
||||
{
|
||||
return FIteratorImpl<true>(*this, Range::Begin(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FSentinelImpl<false> End()
|
||||
{
|
||||
return FSentinelImpl<false>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl<false> End() requires (CCommonRange<const V>)
|
||||
{
|
||||
return FIteratorImpl<false>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FSentinelImpl<true> End() const
|
||||
requires (CRange<const V> && CRegularInvocable<const F&, TRangeReferenceType<const V>>)
|
||||
{
|
||||
return FSentinelImpl<true>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl<true> End() const
|
||||
requires (CCommonRange<const V> && CRegularInvocable<const F&, TRangeReferenceType<const V>>)
|
||||
{
|
||||
return FIteratorImpl<true>(*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<const V> { return Range::Num(Base); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { return Base; }
|
||||
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS V Base;
|
||||
NO_UNIQUE_ADDRESS F Func;
|
||||
|
||||
template <bool bConst>
|
||||
class FIteratorImpl
|
||||
{
|
||||
private:
|
||||
|
||||
using FOwner = TConditional<bConst, const TTransformView, TTransformView>;
|
||||
using FBase = TConditional<bConst, const V, V>;
|
||||
using FFunc = TConditional<bConst, const F, F>;
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReferenceType<FBase>>>;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIteratorType<FBase>>) = default;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl(FIteratorImpl<!bConst> Iter) requires (bConst && CConvertibleTo<TRangeIteratorType<V>, TRangeIteratorType<FBase>>)
|
||||
: Owner(Iter.Owner), Current(MoveTemp(Iter.Current))
|
||||
{ }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS)
|
||||
requires (CSentinelFor<TRangeIteratorType<FBase>, TRangeIteratorType<FBase>>)
|
||||
{
|
||||
return LHS.Current == RHS.Current;
|
||||
}
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS)
|
||||
requires (CSizedSentinelFor<TRangeIteratorType<FBase>, TRangeIteratorType<FBase>>)
|
||||
{
|
||||
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<FBase>) { return Invoke(Owner->Func, Current[Index]); }
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
|
||||
FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange<FBase>) { --Current; return *this; }
|
||||
|
||||
FORCEINLINE constexpr void operator++(int) { Current++; }
|
||||
FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange<FBase>) { return FIteratorImpl(Current++); }
|
||||
FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange<FBase>) { return FIteratorImpl(Current--); }
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) requires (CRandomAccessRange<FBase>) { Current += Offset; return *this; }
|
||||
FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) requires (CRandomAccessRange<FBase>) { Current -= Offset; return *this; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(FIteratorImpl Iter, ptrdiff Offset) requires (CRandomAccessRange<FBase>) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; }
|
||||
NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, FIteratorImpl Iter) requires (CRandomAccessRange<FBase>) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const requires (CRandomAccessRange<FBase>) { FIteratorImpl Temp = *this; Temp -= Offset; return Temp; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS)
|
||||
requires (CSizedSentinelFor<TRangeIteratorType<FBase>, TRangeIteratorType<FBase>>)
|
||||
{
|
||||
return LHS.Current - RHS.Current;
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIteratorType<FBase>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIteratorType<FBase> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS FOwner* Owner;
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeIteratorType<FBase> Current;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIteratorType<FBase> InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { }
|
||||
|
||||
template <bool> friend class FIteratorImpl;
|
||||
template <bool> friend class FSentinelImpl;
|
||||
|
||||
friend TTransformView;
|
||||
};
|
||||
|
||||
template <bool bConst>
|
||||
class FSentinelImpl
|
||||
{
|
||||
private:
|
||||
|
||||
using FOwner = TConditional<bConst, const TTransformView, TTransformView>;
|
||||
using FBase = TConditional<bConst, const V, V>;
|
||||
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible<TRangeSentinelType<FBase>>) = default;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(FSentinelImpl<!bConst> Sentinel) requires (bConst && CConvertibleTo<TRangeSentinelType<V>, TRangeSentinelType<FBase>>)
|
||||
: Current(Sentinel.Current)
|
||||
{ }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl<bConst>& InValue) const& { return Current == InValue.Current; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl<bConst>& LHS, const FSentinelImpl& RHS)
|
||||
requires CSizedSentinelFor<TRangeSentinelType<FBase>, TRangeIteratorType<FBase>>
|
||||
{
|
||||
return LHS.Current - RHS.Current;
|
||||
}
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl<bConst>& RHS)
|
||||
requires CSizedSentinelFor<TRangeSentinelType<FBase>, TRangeIteratorType<FBase>>
|
||||
{
|
||||
return RHS.Current - LHS.Current;
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIteratorType<FBase>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIteratorType<FBase> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeSentinelType<FBase> Current;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinelType<FBase> InCurrent) : Current(InCurrent) { }
|
||||
|
||||
friend TTransformView;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename F>
|
||||
TTransformView(R&&, F) -> TTransformView<TAllView<R>, F>;
|
||||
|
||||
static_assert(CRandomAccessRange<TTransformView<TSingleView<int>, decltype([](auto) { return 0; })>>);
|
||||
static_assert( CCommonRange<TTransformView<TSingleView<int>, decltype([](auto) { return 0; })>>);
|
||||
static_assert( CSizedRange<TTransformView<TSingleView<int>, decltype([](auto) { return 0; })>>);
|
||||
static_assert( CView<TTransformView<TSingleView<int>, decltype([](auto) { return 0; })>>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** Creates A view adapter that includes all elements of a range. */
|
||||
template <CViewableRange R>
|
||||
NODISCARD FORCEINLINE constexpr TAllView<R> All(R&& InRange)
|
||||
{
|
||||
return TAllView<R>(Forward<R>(InRange));
|
||||
}
|
||||
|
||||
/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */
|
||||
template <CViewableRange R, typename Pred> requires (requires { TFilterView(DeclVal<R>(), DeclVal<Pred>()); })
|
||||
NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate)
|
||||
{
|
||||
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||
}
|
||||
|
||||
/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */
|
||||
template <typename Pred>
|
||||
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
|
||||
{
|
||||
return [&Predicate]<CViewableRange R>(R&& Base) requires (requires { TFilterView(DeclVal<R>(), DeclVal<Pred>()); })
|
||||
{
|
||||
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||
};
|
||||
}
|
||||
|
||||
/** Creates A view adapter of a sequence that applies a transformation function to each element. */
|
||||
template <CViewableRange R, typename F> requires (requires { TTransformView(DeclVal<R>(), DeclVal<F>()); })
|
||||
NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func)
|
||||
{
|
||||
return TTransformView(Forward<R>(Base), Forward<F>(Func));
|
||||
}
|
||||
|
||||
/** Creates A view adapter of a sequence that applies a transformation function to each element. */
|
||||
template <typename F>
|
||||
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
|
||||
{
|
||||
return [&Func]<CViewableRange R>(R&& Base) requires (requires { TTransformView(DeclVal<R>(), DeclVal<F>()); })
|
||||
{
|
||||
return TTransformView(Forward<R>(Base), Forward<F>(Func));
|
||||
};
|
||||
}
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
template <CRange R, typename T> requires (CRange<TInvokeResult<T, R>>)
|
||||
NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& View)
|
||||
{
|
||||
return Invoke(Forward<T>(View), Forward<R>(Range));
|
||||
}
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
171
Redcraft.Utility/Source/Public/Range/AllView.h
Normal file
171
Redcraft.Utility/Source/Public/Range/AllView.h
Normal file
@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Range/View.h"
|
||||
#include "Range/Utility.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 that references other range.
|
||||
* No matter which it is base range, the reference view always satisfies the same range concept.
|
||||
*/
|
||||
template <CRange R> requires (CObject<R>)
|
||||
class TRefView : public IBasicViewInterface<TRefView<R>>
|
||||
{
|
||||
private:
|
||||
|
||||
// Use the function to check constructability.
|
||||
static void Func(R&);
|
||||
static void Func(R&&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
template <typename T> requires (!CSameAs<TRemoveCVRef<T>, TRefView> && CConvertibleTo<T, R&> && requires { Func(DeclVal<T>()); })
|
||||
FORCEINLINE constexpr TRefView(T&& InRange) : Ptr(AddressOf(static_cast<R&>(Forward<T>(InRange)))) { }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TRangeIterator<R> Begin() const { return Range::Begin(*Ptr); }
|
||||
NODISCARD FORCEINLINE constexpr TRangeSentinel<R> End() const { return Range::End (*Ptr); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange<R>) { return Range::GetData(*Ptr); }
|
||||
NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange<R>) { return Range::Num (*Ptr); }
|
||||
NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (requires(R Range) { Range::IsEmpty(Range); }) { return Range::IsEmpty(*Ptr); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr R& GetBase() const { return *Ptr; }
|
||||
|
||||
private:
|
||||
|
||||
R* Ptr;
|
||||
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
TRefView(R&) -> TRefView<R>;
|
||||
|
||||
static_assert( CInputRange<TRefView<IRange< IInputIterator<int&>>>>);
|
||||
static_assert( CForwardRange<TRefView<IRange< IForwardIterator<int&>>>>);
|
||||
static_assert(CBidirectionalRange<TRefView<IRange<IBidirectionalIterator<int&>>>>);
|
||||
static_assert( CRandomAccessRange<TRefView<IRange< IRandomAccessIterator<int&>>>>);
|
||||
static_assert( CContiguousRange<TRefView<IRange< IContiguousIterator<int&>>>>);
|
||||
|
||||
static_assert(CCommonRange<TRefView<ICommonRange< IForwardIterator<int>>>>);
|
||||
static_assert( CSizedRange<TRefView< ISizedRange<IInputOrOutputIterator<int>>>>);
|
||||
static_assert( CView<TRefView< IRange<IInputOrOutputIterator<int>>>>);
|
||||
|
||||
static_assert(COutputRange<TRefView<IRange<IOutputIterator<int&>>>, int>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
template <typename T>
|
||||
constexpr bool bEnableBorrowedRange<Range::TRefView<T>> = true;
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/**
|
||||
* A view adapter that has unique ownership of a range.
|
||||
* No matter which it is base range, the reference view always satisfies the same range concept.
|
||||
* Specify, the base range type must be movable, and the owning view always is movable but not copyable.
|
||||
*/
|
||||
template <CRange R> requires (CMovable<R> && !NAMESPACE_PRIVATE::TIsInitializerList<R>::Value)
|
||||
class TOwningView : public IBasicViewInterface<TOwningView<R>>
|
||||
{
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr TOwningView() requires (CDefaultConstructible<R>) = 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 auto Begin() { return Range::Begin(Base); }
|
||||
NODISCARD FORCEINLINE constexpr auto End() { return Range::End (Base); }
|
||||
NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange<const R>) { return Range::Begin(Base); }
|
||||
NODISCARD FORCEINLINE constexpr auto End() const requires (CRange<const R>) { return Range::End (Base); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< R>) { return Range::GetData(Base); }
|
||||
NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange<const R>) { 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<const R>) { 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( CInputRange<TOwningView<IRange< IInputIterator<int&>>>>);
|
||||
static_assert( CForwardRange<TOwningView<IRange< IForwardIterator<int&>>>>);
|
||||
static_assert(CBidirectionalRange<TOwningView<IRange<IBidirectionalIterator<int&>>>>);
|
||||
static_assert( CRandomAccessRange<TOwningView<IRange< IRandomAccessIterator<int&>>>>);
|
||||
static_assert( CContiguousRange<TOwningView<IRange< IContiguousIterator<int&>>>>);
|
||||
|
||||
static_assert(CCommonRange<TOwningView<ICommonRange< IForwardIterator<int>>>>);
|
||||
static_assert( CSizedRange<TOwningView< ISizedRange<IInputOrOutputIterator<int>>>>);
|
||||
static_assert( CView<TOwningView< IRange<IInputOrOutputIterator<int>>>>);
|
||||
|
||||
static_assert(COutputRange<TOwningView<IRange<IOutputIterator<int&>>>, int>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
template <typename T>
|
||||
constexpr bool bEnableBorrowedRange<Range::TOwningView<T>> = bEnableBorrowedRange<T>;
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** Creates A view adapter that includes all elements of a range. */
|
||||
template <CViewableRange R>
|
||||
NODISCARD FORCEINLINE constexpr auto All(R&& InRange)
|
||||
{
|
||||
if constexpr (CView<TDecay<R>>)
|
||||
{
|
||||
return TDecay<R>(Forward<R>(InRange));
|
||||
}
|
||||
|
||||
else if constexpr (requires { TRefView(Forward<R>(InRange)); })
|
||||
{
|
||||
return TRefView(Forward<R>(InRange));
|
||||
}
|
||||
|
||||
else return TOwningView(Forward<R>(InRange));
|
||||
}
|
||||
|
||||
/** A view adapter that includes all elements of a range. */
|
||||
template <CViewableRange R>
|
||||
using TAllView = decltype(Range::All(DeclVal<R>()));
|
||||
|
||||
static_assert( CInputRange<TAllView<IRange< IInputIterator<int&>>>>);
|
||||
static_assert( CForwardRange<TAllView<IRange< IForwardIterator<int&>>>>);
|
||||
static_assert(CBidirectionalRange<TAllView<IRange<IBidirectionalIterator<int&>>>>);
|
||||
static_assert( CRandomAccessRange<TAllView<IRange< IRandomAccessIterator<int&>>>>);
|
||||
static_assert( CContiguousRange<TAllView<IRange< IContiguousIterator<int&>>>>);
|
||||
|
||||
static_assert(CCommonRange<TAllView<ICommonRange< IForwardIterator<int>>>>);
|
||||
static_assert( CSizedRange<TAllView< ISizedRange<IInputOrOutputIterator<int>>>>);
|
||||
static_assert( CView<TAllView< IRange<IInputOrOutputIterator<int>>>>);
|
||||
|
||||
static_assert(COutputRange<TAllView<IRange<IOutputIterator<int&>>>, int>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -250,8 +250,6 @@ private:
|
||||
|
||||
NO_UNIQUE_ADDRESS FSizeType Count;
|
||||
|
||||
public:
|
||||
|
||||
class FIteratorImpl final
|
||||
{
|
||||
public:
|
||||
|
187
Redcraft.Utility/Source/Public/Range/FilterView.h
Normal file
187
Redcraft.Utility/Source/Public/Range/FilterView.h
Normal file
@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Range/View.h"
|
||||
#include "Range/Utility.h"
|
||||
#include "Range/AllView.h"
|
||||
#include "Memory/Address.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 that consists of the elements of a range that satisfies a predicate.
|
||||
* When based on an input view, the filter view satisfies at least an input view up to a bidirectional view.
|
||||
* When based on a common view, the counted iterator satisfies a common view.
|
||||
*/
|
||||
template <CInputRange V, CPredicate<TRangeReference<V>> Pred> requires (CView<V> && CObject<Pred> && CMoveConstructible<Pred>)
|
||||
class TFilterView : public IBasicViewInterface<TFilterView<V, Pred>>
|
||||
{
|
||||
private:
|
||||
|
||||
class FIteratorImpl;
|
||||
class FSentinelImpl;
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TRangeElement<V>;
|
||||
using Reference = TRangeReference<V>;
|
||||
|
||||
using Iterator = FIteratorImpl;
|
||||
|
||||
using Sentinel = TConditional<CCommonRange<V>, FIteratorImpl, FSentinelImpl>;
|
||||
|
||||
FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible<V> && CDefaultConstructible<Pred>) = 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<bool>(GetPredicate(), *Iter)) break;
|
||||
|
||||
++Iter;
|
||||
}
|
||||
while (false);
|
||||
|
||||
if constexpr (!CForwardRange<V>) return MoveTemp(Iter);
|
||||
|
||||
return Iter;
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); }
|
||||
|
||||
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;
|
||||
|
||||
class FIteratorImpl final
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TIteratorElementType<TRangeIterator<V>>;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<V>>) { } // Use '{ }' instead of '= default;' to avoid MSVC bug.
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS)
|
||||
{
|
||||
return LHS.GetBase() == RHS.GetBase();
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr TRangeReference<V> operator*() const { return *GetBase(); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const TRangeIterator<V> Iter) { { ToAddress(Iter) } -> CSameAs<TIteratorPointer<TRangeIterator<V>>>; }) { return ToAddress(GetBase()); }
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator++()
|
||||
{
|
||||
do ++Current; while (*this != Owner->End() && !InvokeResult<bool>(Owner->GetPredicate(), *Current));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalIterator<TRangeIterator<V>>)
|
||||
{
|
||||
do --Current; while (!InvokeResult<bool>(Owner->GetPredicate(), *Current));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr void operator++(int) { Current++; }
|
||||
FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardIterator<TRangeIterator<V>>) { return FIteratorImpl(Owner, Current++); }
|
||||
FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalIterator<TRangeIterator<V>>) { return FIteratorImpl(Owner, Current--); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIterator<V>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIterator<V> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
TFilterView* Owner;
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeIterator<V> Current;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl(TFilterView& InOwner, TRangeIterator<V> InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { }
|
||||
|
||||
friend FSentinelImpl;
|
||||
|
||||
friend TFilterView;
|
||||
};
|
||||
|
||||
class FSentinelImpl final
|
||||
{
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl() = default;
|
||||
|
||||
NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Current == InValue.Current; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeSentinel<V>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeSentinel<V> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
TRangeSentinel<V> Current;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(TFilterView& InOwner, TRangeSentinel<V> InCurrent) : Current(InCurrent) { }
|
||||
|
||||
friend TFilterView;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename Pred>
|
||||
TFilterView(R&&, Pred) -> TFilterView<TAllView<R>, Pred>;
|
||||
|
||||
static_assert( CInputRange<TFilterView<TAllView<IRange< IInputIterator<int&>>>, bool(*)(int)>>);
|
||||
static_assert( CForwardRange<TFilterView<TAllView<IRange< IForwardIterator<int&>>>, bool(*)(int)>>);
|
||||
static_assert(CBidirectionalRange<TFilterView<TAllView<IRange<IBidirectionalIterator<int&>>>, bool(*)(int)>>);
|
||||
static_assert(CBidirectionalRange<TFilterView<TAllView<IRange< IRandomAccessIterator<int&>>>, bool(*)(int)>>);
|
||||
static_assert(CBidirectionalRange<TFilterView<TAllView<IRange< IContiguousIterator<int&>>>, bool(*)(int)>>);
|
||||
|
||||
static_assert(CCommonRange<TFilterView<TAllView<ICommonRange<IForwardIterator<int>>>, bool(*)(int)>>);
|
||||
static_assert( CView<TFilterView<TAllView< IRange< IInputIterator<int>>>, bool(*)(int)>>);
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */
|
||||
template <CViewableRange R, typename Pred> requires (requires { TFilterView(DeclVal<R&&>(), DeclVal<Pred&&>()); })
|
||||
NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate)
|
||||
{
|
||||
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||
}
|
||||
|
||||
/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */
|
||||
template <typename Pred>
|
||||
NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate)
|
||||
{
|
||||
return [&Predicate]<CViewableRange R> requires (requires { TFilterView(DeclVal<R&&>(), DeclVal<Pred&&>()); }) (R&& Base)
|
||||
{
|
||||
return TFilterView(Forward<R>(Base), Forward<Pred>(Predicate));
|
||||
};
|
||||
}
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -4,3 +4,6 @@
|
||||
#include "Range/Utility.h"
|
||||
#include "Range/View.h"
|
||||
#include "Range/Factory.h"
|
||||
#include "Range/AllView.h"
|
||||
#include "Range/FilterView.h"
|
||||
#include "Range/TransformView.h"
|
||||
|
234
Redcraft.Utility/Source/Public/Range/TransformView.h
Normal file
234
Redcraft.Utility/Source/Public/Range/TransformView.h
Normal file
@ -0,0 +1,234 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Range/View.h"
|
||||
#include "Range/Utility.h"
|
||||
#include "Range/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 counted iterator satisfies a common view. When based on a sized view,
|
||||
* the counted iterator 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 <CInputRange V, CMoveConstructible F> requires (CView<V> && CObject<F>
|
||||
&& CRegularInvocable<F&, TRangeReference<V>> && CReferenceable<TInvokeResult<F&, TRangeReference<V>>>)
|
||||
class TTransformView : public IBasicViewInterface<TTransformView<V, F>>
|
||||
{
|
||||
private:
|
||||
|
||||
template <bool bConst> class FIteratorImpl;
|
||||
template <bool bConst> class FSentinelImpl;
|
||||
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible<V>&& CDefaultConstructible<F>) = default;
|
||||
|
||||
FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto Begin()
|
||||
{
|
||||
return FIteratorImpl<false>(*this, Range::Begin(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange<const V> && CRegularInvocable<const F&, TRangeReference<const V>>)
|
||||
{
|
||||
return FIteratorImpl<true>(*this, Range::Begin(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto End()
|
||||
{
|
||||
if constexpr (CCommonRange<V>)
|
||||
{
|
||||
return FIteratorImpl<false>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
else return FSentinelImpl<false>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr auto End() const requires (CRange<const V> && CRegularInvocable<const F&, TRangeReference<const V>>)
|
||||
{
|
||||
if constexpr (CCommonRange<const V>)
|
||||
{
|
||||
return FIteratorImpl<true>(*this, Range::End(Base));
|
||||
}
|
||||
|
||||
else return FSentinelImpl<true>(*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<const V>) { return Range::Num(Base); }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible<V>) { return Base; }
|
||||
NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS V Base;
|
||||
NO_UNIQUE_ADDRESS F Func;
|
||||
|
||||
template <bool bConst>
|
||||
class FIteratorImpl
|
||||
{
|
||||
private:
|
||||
|
||||
using FOwner = TConditional<bConst, const TTransformView, TTransformView>;
|
||||
using FBase = TConditional<bConst, const V, V>;
|
||||
using FFunc = TConditional<bConst, const F, F>;
|
||||
|
||||
public:
|
||||
|
||||
using ElementType = TRemoveCVRef<TInvokeResult<FFunc&, TRangeReference<FBase>>>;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<TRangeIterator<FBase>>) = default;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl(FIteratorImpl<!bConst> Iter) requires (bConst && CConvertibleTo<TRangeIterator<V>, TRangeIterator<FBase>>)
|
||||
: Owner(Iter.Owner), Current(MoveTemp(Iter).GetBase())
|
||||
{ }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable<TRangeIterator<FBase>>)
|
||||
{
|
||||
return LHS.GetBase() == RHS.GetBase();
|
||||
}
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CThreeWayComparable<TRangeIterator<FBase>>)
|
||||
{
|
||||
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<FBase>) { return Invoke(Owner->Func, GetBase()[Index]); }
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
|
||||
FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange<FBase>) { --Current; return *this; }
|
||||
|
||||
FORCEINLINE constexpr void operator++(int) { Current++; }
|
||||
FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange<FBase>) { return FIteratorImpl(Current++); }
|
||||
FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange<FBase>) { return FIteratorImpl(Current--); }
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) requires (CRandomAccessRange<FBase>) { Current += Offset; return *this; }
|
||||
FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) requires (CRandomAccessRange<FBase>) { Current -= Offset; return *this; }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset) const requires (CRandomAccessRange<FBase>) { FIteratorImpl Temp = *this; Temp += Offset; return Temp; }
|
||||
NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const requires (CRandomAccessRange<FBase>) { FIteratorImpl Temp = *this; Temp -= Offset; return Temp; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, const FIteratorImpl& Iter) requires (CRandomAccessRange<FBase>) { return Iter + Offset; }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSizedSentinelFor<TRangeIterator<FBase>, TRangeIterator<FBase>>)
|
||||
{
|
||||
return LHS.GetBase() - RHS.GetBase();
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIterator<FBase>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIterator<FBase> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS FOwner* Owner;
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeIterator<FBase> Current;
|
||||
|
||||
FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIterator<FBase> InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { }
|
||||
|
||||
template <bool> friend class FIteratorImpl;
|
||||
template <bool> friend class FSentinelImpl;
|
||||
|
||||
friend TTransformView;
|
||||
};
|
||||
|
||||
template <bool bConst>
|
||||
class FSentinelImpl
|
||||
{
|
||||
private:
|
||||
|
||||
using FOwner = TConditional<bConst, const TTransformView, TTransformView>;
|
||||
using FBase = TConditional<bConst, const V, V>;
|
||||
|
||||
public:
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible<TRangeSentinel<FBase>>) = default;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(FSentinelImpl<!bConst> Sentinel) requires (bConst && CConvertibleTo<TRangeSentinel<V>, TRangeSentinel<FBase>>)
|
||||
: Current(Sentinel.GetBase())
|
||||
{ }
|
||||
|
||||
NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl<bConst>& InValue) const& { return Current == InValue.GetBase(); }
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl<bConst>& LHS, const FSentinelImpl& RHS)
|
||||
requires CSizedSentinelFor<TRangeSentinel<FBase>, TRangeIterator<FBase>>
|
||||
{
|
||||
return LHS.GetBase() - RHS.GetBase();
|
||||
}
|
||||
|
||||
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl<bConst>& RHS)
|
||||
requires CSizedSentinelFor<TRangeSentinel<FBase>, TRangeIterator<FBase>>
|
||||
{
|
||||
return RHS.GetBase() - LHS.GetBase();
|
||||
}
|
||||
|
||||
NODISCARD FORCEINLINE constexpr const TRangeIterator<FBase>& GetBase() const& { return Current; }
|
||||
NODISCARD FORCEINLINE constexpr TRangeIterator<FBase> GetBase() && { return MoveTemp(Current); }
|
||||
|
||||
private:
|
||||
|
||||
NO_UNIQUE_ADDRESS TRangeSentinel<FBase> Current;
|
||||
|
||||
FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinel<FBase> InCurrent) : Current(InCurrent) { }
|
||||
|
||||
friend TTransformView;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename R, typename F>
|
||||
TTransformView(R&&, F) -> TTransformView<TAllView<R>, F>;
|
||||
|
||||
static_assert( CInputRange<TTransformView<TAllView<IRange< IInputIterator<int&>>>, int(*)(int)>>);
|
||||
static_assert( CForwardRange<TTransformView<TAllView<IRange< IForwardIterator<int&>>>, int(*)(int)>>);
|
||||
static_assert(CBidirectionalRange<TTransformView<TAllView<IRange<IBidirectionalIterator<int&>>>, int(*)(int)>>);
|
||||
static_assert( CRandomAccessRange<TTransformView<TAllView<IRange< IRandomAccessIterator<int&>>>, int(*)(int)>>);
|
||||
static_assert( CRandomAccessRange<TTransformView<TAllView<IRange< IContiguousIterator<int&>>>, int(*)(int)>>);
|
||||
|
||||
static_assert(CCommonRange<TTransformView<TAllView<ICommonRange<IForwardIterator<int>>>, int(*)(int)>>);
|
||||
static_assert( CSizedRange<TTransformView<TAllView< ISizedRange< IInputIterator<int>>>, int(*)(int)>>);
|
||||
static_assert( CView<TTransformView<TAllView< IRange< IInputIterator<int>>>, int(*)(int)>>);
|
||||
|
||||
static_assert(COutputRange<TTransformView<TAllView<IRange<IForwardIterator<int>>>, 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 <CViewableRange R, typename F> requires (requires { TTransformView(DeclVal<R&&>(), DeclVal<F&&>()); })
|
||||
NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func)
|
||||
{
|
||||
return TTransformView(Forward<R>(Base), Forward<F>(Func));
|
||||
}
|
||||
|
||||
/** Creates A view adapter of a sequence that applies a transformation function to each element. */
|
||||
template <typename F>
|
||||
NODISCARD FORCEINLINE constexpr auto Transform(F&& Func)
|
||||
{
|
||||
return [&Func]<CViewableRange R> requires (requires { TTransformView(DeclVal<R&&>(), DeclVal<F&&>()); }) (R&& Base)
|
||||
{
|
||||
return TTransformView(Forward<R>(Base), Forward<F>(Func));
|
||||
};
|
||||
}
|
||||
|
||||
NAMESPACE_END(Range)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -12,7 +12,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
|
||||
NAMESPACE_BEGIN(Range)
|
||||
|
||||
/** A helper class template for defining a view interface. Not directly instantiable. */
|
||||
template <typename T> requires (CClass<T> && CSameAs<T, TRemoveCV<T>>)
|
||||
template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
|
||||
class IBasicViewInterface
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user