Compare commits

...

5 Commits

10 changed files with 1113 additions and 1010 deletions

View File

@ -30,7 +30,8 @@ public:
using ElementType = TIteratorElement<I>;
FORCEINLINE constexpr TMoveIterator() = default;
FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible<I>) = default;
FORCEINLINE constexpr TMoveIterator(const TMoveIterator&) = default;
FORCEINLINE constexpr TMoveIterator(TMoveIterator&&) = default;
FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator&) = default;
@ -45,7 +46,7 @@ public:
template <CInputIterator J> requires (!CSameAs<I, J> && CConvertibleTo<const J&, I> && CAssignableFrom<I&, const J&>)
FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator<J>& InValue) { Current = InValue.GetBase(); return *this; }
template <CInputIterator J> requires (CSentinelFor<J, I>)
template <CInputIterator J> requires (CEqualityComparable<I, J>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TMoveIterator& LHS, const TMoveIterator<J>& RHS) { return LHS.GetBase() == RHS.GetBase(); }
template <CInputIterator J> requires (CThreeWayComparable<I, J>)
@ -70,7 +71,7 @@ public:
NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(ptrdiff Offset, const TMoveIterator& Iter) requires (CRandomAccessIterator<I>) { return Iter + Offset; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CRandomAccessIterator<I>) { return LHS.GetBase() - RHS.GetBase(); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor<I, I>) { return LHS.GetBase() - RHS.GetBase(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }

View File

@ -44,7 +44,7 @@ public:
template <CBidirectionalIterator J> requires (!CSameAs<I, J> && CConvertibleTo<const J&, I> && CAssignableFrom<I&, const J&>)
FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator<J>& InValue) { Current = InValue.GetBase(); return *this; }
template <CBidirectionalIterator J> requires (CSentinelFor<J, I>)
template <CBidirectionalIterator J> requires (CEqualityComparable<I, J>)
NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator<J>& RHS) { return LHS.GetBase() == RHS.GetBase(); }
template <CBidirectionalIterator J> requires (CThreeWayComparable<I, J>)
@ -70,7 +70,7 @@ public:
NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, const TReverseIterator& Iter) requires (CRandomAccessIterator<I>) { return Iter + Offset; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator<I>) { return RHS.GetBase() - LHS.GetBase(); }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CSizedSentinelFor<I, I>) { return RHS.GetBase() - LHS.GetBase(); }
NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; }
NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); }

File diff suppressed because it is too large Load Diff

View 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

View File

@ -0,0 +1,357 @@
#pragma once
#include "CoreTypes.h"
#include "Range/View.h"
#include "Range/Utility.h"
#include "Memory/Address.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 type that produces a view of no elements of a particular type. */
template <CObject T>
class TEmptyView : public IBasicViewInterface<TEmptyView<T>>
{
public:
using ElementType = T;
using Reference = T&;
using Iterator = T*;
using Sentinel = T*;
FORCEINLINE constexpr TEmptyView() = default;
NODISCARD static FORCEINLINE constexpr Iterator Begin() { return nullptr; }
NODISCARD static FORCEINLINE constexpr Sentinel End() { return nullptr; }
NODISCARD static FORCEINLINE constexpr T* GetData() { return nullptr; }
NODISCARD static FORCEINLINE constexpr size_t Num() { return 0; }
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return true; }
};
static_assert(CContiguousRange<TEmptyView<int>>);
static_assert( CCommonRange<TEmptyView<int>>);
static_assert( CSizedRange<TEmptyView<int>>);
static_assert( CView<TEmptyView<int>>);
NAMESPACE_END(Range)
template <typename T>
constexpr bool bEnableBorrowedRange<Range::TEmptyView<T>> = true;
NAMESPACE_BEGIN(Range)
/** A view type that contains exactly one element of a specified value. */
template <CObject T> requires (CMoveConstructible<T>)
class TSingleView : public IBasicViewInterface<TSingleView<T>>
{
public:
using ElementType = T;
using Reference = T&;
using ConstReference = const T&;
using Iterator = T*;
using ConstIterator = const T*;
using Sentinel = T*;
using ConstSentinel = const T*;
FORCEINLINE constexpr TSingleView() requires (CDefaultConstructible<T>) = default;
FORCEINLINE constexpr explicit TSingleView(const T& InValue) requires (CCopyConstructible<T>) : Value(InValue) { }
FORCEINLINE constexpr explicit TSingleView(T&& InValue) : Value(MoveTemp(InValue)) { }
template <typename... Ts> requires (CConstructibleFrom<T, Ts...>)
FORCEINLINE constexpr explicit TSingleView(FInPlace, Ts&&... Args) : Value(Forward<Ts>(Args)...) { }
FORCEINLINE constexpr Iterator Begin() { return GetData(); }
FORCEINLINE constexpr ConstIterator Begin() const { return GetData(); }
FORCEINLINE constexpr Sentinel End() { return GetData() + 1; }
FORCEINLINE constexpr ConstSentinel End() const { return GetData() + 1; }
NODISCARD FORCEINLINE constexpr T* GetData() { return AddressOf(Value); }
NODISCARD FORCEINLINE constexpr const T* GetData() const { return AddressOf(Value); }
NODISCARD static FORCEINLINE constexpr size_t Num() { return 1; }
NODISCARD static FORCEINLINE constexpr bool IsEmpty() { return false; }
private:
NO_UNIQUE_ADDRESS T Value;
};
template <typename T>
TSingleView(T) -> TSingleView<T>;
static_assert(CContiguousRange<TSingleView<int>>);
static_assert( CCommonRange<TSingleView<int>>);
static_assert( CSizedRange<TSingleView<int>>);
static_assert( CView<TSingleView<int>>);
/** A view type that generates a sequence of elements by repeatedly incrementing an initial value. Can be either bounded or unbounded. */
template <CWeaklyIncrementable W, CWeaklyEqualityComparable<W> S = FUnreachableSentinel> requires (CSemiregular<S> && CCopyable<W>)
class TIotaView : public IBasicViewInterface<TIotaView<W, S>>
{
private:
class FIteratorImpl;
class FSentinelImpl;
public:
using ElementType = TRemoveCV<W>;
using Reference = W;
using Iterator = FIteratorImpl;
using Sentinel = TConditional<CSameAs<W, S>, FIteratorImpl, FSentinelImpl>;
FORCEINLINE constexpr TIotaView() requires (CDefaultConstructible<W>) = default;
FORCEINLINE constexpr explicit TIotaView(W InValue) requires (CDefaultConstructible<S>) : First(InValue), Last() { }
FORCEINLINE constexpr explicit TIotaView(TIdentity<W> InValue, TIdentity<S> InLast) : First(InValue), Last(InLast) { }
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, Sentinel InLast) : First(InFirst.Value), Last(InLast.Value) { }
FORCEINLINE constexpr explicit TIotaView(Iterator InFirst, FUnreachableSentinel) requires (CSameAs<S, FUnreachableSentinel>) : First(InFirst.Value) { }
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(First); }
NODISCARD FORCEINLINE constexpr Sentinel End() const { return Sentinel(Last); }
NODISCARD FORCEINLINE constexpr size_t Num() const requires ((CIntegral<W> && CIntegral<S>) || CSizedSentinelFor<S, W>) { return Last - First; }
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return First == Last; }
private:
NO_UNIQUE_ADDRESS W First;
NO_UNIQUE_ADDRESS S Last;
class FIteratorImpl final
{
public:
using ElementType = TRemoveCV<W>;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable<W>) { return LHS.Value == RHS.Value; }
NODISCARD FORCEINLINE constexpr Reference operator*() const { return Value; }
NODISCARD FORCEINLINE constexpr const W* operator->() const { return AddressOf(Value); }
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Value; return *this; }
FORCEINLINE constexpr FIteratorImpl operator++(int) { FIteratorImpl Temp = *this; ++Value; return Temp; }
private:
NO_UNIQUE_ADDRESS W Value;
constexpr explicit FIteratorImpl(W InValue) : Value(InValue) { }
friend FSentinelImpl;
friend TIotaView;
};
class FSentinelImpl final
{
public:
FORCEINLINE constexpr FSentinelImpl() = default;
NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Value == InValue.Value; }
private:
NO_UNIQUE_ADDRESS S Value;
FORCEINLINE constexpr FSentinelImpl(S InValue) : Value(InValue) { }
friend TIotaView;
};
};
template <typename T, typename U>
TIotaView(T, U) -> TIotaView<T, U>;
static_assert(CForwardRange<TIotaView<int>>);
static_assert( CView<TIotaView<int>>);
NAMESPACE_END(Range)
template <typename T, typename U>
constexpr bool bEnableBorrowedRange<Range::TIotaView<T, U>> = true;
NAMESPACE_BEGIN(Range)
/** A view type that generates a sequence of elements by repeatedly producing the same value. Can be either bounded or unbounded. */
template <CObject W, bool bIsUnreachable = true> requires (CMoveConstructible<W> && CSameAs<W, TRemoveCV<W>>)
class TRepeatView : public IBasicViewInterface<TRepeatView<W, bIsUnreachable>>
{
private:
class FIteratorImpl;
public:
using ElementType = W;
using Reference = const W&;
using Iterator = FIteratorImpl;
using Sentinel = TConditional<bIsUnreachable, FUnreachableSentinel, Iterator>;
FORCEINLINE constexpr TRepeatView() requires (CDefaultConstructible<W>) = default;
FORCEINLINE constexpr explicit TRepeatView(const W& InValue) requires (bIsUnreachable && CCopyConstructible<W>) : Value(InValue) { }
FORCEINLINE constexpr explicit TRepeatView(W&& InValue) requires (bIsUnreachable) : Value(MoveTemp(InValue)) { }
FORCEINLINE constexpr explicit TRepeatView(const W& InValue, size_t InCount) requires (!bIsUnreachable && CCopyConstructible<W>) : Value(MoveTemp(InValue)), Count(InCount) { }
FORCEINLINE constexpr explicit TRepeatView(W&& InValue, size_t InCount) requires (!bIsUnreachable) : Value(MoveTemp(InValue)), Count(InCount) { }
template <typename... Ts> requires (CConstructibleFrom<W, Ts...>)
FORCEINLINE constexpr explicit TRepeatView(FInPlace, Ts&&... Args, size_t InCount) : Value(Forward<Ts>(Args)...), Count(InCount) { }
NODISCARD FORCEINLINE constexpr Iterator Begin() const { return Iterator(Value, 0); }
NODISCARD FORCEINLINE constexpr Sentinel End() const
{
if constexpr (bIsUnreachable)
{
return UnreachableSentinel;
}
else return Sentinel(Value, Count);
}
NODISCARD FORCEINLINE constexpr size_t Num() const requires (!bIsUnreachable) { return Count; }
private:
using FSizeType = TConditional<bIsUnreachable, FUnreachableSentinel, size_t>;
NO_UNIQUE_ADDRESS W Value;
NO_UNIQUE_ADDRESS FSizeType Count;
class FIteratorImpl final
{
public:
using ElementType = W;
FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible<W>) = default;
NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return LHS.Current == RHS.Current; }
NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return LHS.Current <=> RHS.Current; }
NODISCARD FORCEINLINE constexpr Reference operator*() const { return *Ptr; }
NODISCARD FORCEINLINE constexpr const W* operator->() const { return Ptr; }
NODISCARD FORCEINLINE constexpr Reference operator[](ptrdiff) const { return *Ptr; }
FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; }
FORCEINLINE constexpr FIteratorImpl& operator--() { --Current; return *this; }
FORCEINLINE constexpr FIteratorImpl operator++(int) { FIteratorImpl Temp = *this; --Current; return Temp; }
FORCEINLINE constexpr FIteratorImpl operator--(int) { FIteratorImpl Temp = *this; ++Current; return Temp; }
FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) { Current -= Offset; return *this; }
FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) { Current += Offset; return *this; }
NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(FIteratorImpl Iter, ptrdiff Offset) { FIteratorImpl Temp = Iter; Temp -= Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, FIteratorImpl Iter) { FIteratorImpl Temp = Iter; Temp -= Offset; return Temp; }
NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const { FIteratorImpl Temp = *this; Temp += Offset; return Temp; }
NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) { return RHS.Current - LHS.Current; }
private:
const W* Ptr;
NO_UNIQUE_ADDRESS size_t Current;
FORCEINLINE constexpr FIteratorImpl(const W& InObject, size_t InCurrent) : Ptr(AddressOf(InObject)), Current(InCurrent) { }
friend TRepeatView;
};
};
template <typename W>
TRepeatView(W) -> TRepeatView<W>;
template <typename W>
TRepeatView(W, size_t) -> TRepeatView<W, false>;
static_assert(CRandomAccessRange<TRepeatView<int, false>>);
static_assert( CCommonRange<TRepeatView<int, false>>);
static_assert( CSizedRange<TRepeatView<int, false>>);
static_assert( CView<TRepeatView<int, false>>);
NAMESPACE_END(Range)
NAMESPACE_BEGIN(Range)
/** A view of no elements of a particular type. */
template <CObject T>
inline constexpr TEmptyView<T> Empty;
/** Creates a view that contains exactly one element of a specified value. */
template <typename T> requires (CObject<TDecay<T>> && CMoveConstructible<TDecay<T>>)
NODISCARD FORCEINLINE constexpr TSingleView<TDecay<T>> Single(T&& Value)
{
return TSingleView<TDecay<T>>(Forward<T>(Value));
}
/** Creates a view that generates a sequence of elements by repeatedly incrementing an initial value. */
template <typename W> requires (CWeaklyIncrementable<TDecay<W>> && CCopyable<TDecay<W>>)
NODISCARD FORCEINLINE constexpr TIotaView<TDecay<W>> Iota(W&& Value)
{
return TIotaView<TDecay<W>>(Forward<W>(Value));
}
/** Creates a view that generates a sequence of elements by repeatedly incrementing an initial value. */
template <typename W, typename S> requires (CWeaklyIncrementable<TDecay<W>> && CWeaklyEqualityComparable<W, S> && CCopyable<TDecay<W>> && CSemiregular<TDecay<S>>)
NODISCARD FORCEINLINE constexpr TIotaView<TDecay<W>, TDecay<S>> Iota(W&& Value, S&& Last)
{
return TIotaView<TDecay<W>, TDecay<S>>(Forward<W>(Value), Forward<S>(Last));
}
/** Creates a view that generates a sequence of elements by repeatedly producing the same value. */
template <typename W> requires (CObject<TDecay<W>> && CMoveConstructible<TDecay<W>>)
NODISCARD FORCEINLINE constexpr TRepeatView<TDecay<W>> Repeat(W&& Value)
{
return TRepeatView<TDecay<W>>(Forward<W>(Value));
}
/** Creates a view that generates a sequence of elements by repeatedly producing the same value. */
template <typename W> requires (CObject<TDecay<W>> && CMoveConstructible<TDecay<W>>)
NODISCARD FORCEINLINE constexpr TRepeatView<TDecay<W>, false> Repeat(W&& Value, size_t Count)
{
return TRepeatView<TDecay<W>, false>(Forward<W>(Value), Count);
}
NAMESPACE_END(Range)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View 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

View File

@ -2,3 +2,8 @@
#include "CoreTypes.h"
#include "Range/Utility.h"
#include "Range/View.h"
#include "Range/Factory.h"
#include "Range/AllView.h"
#include "Range/FilterView.h"
#include "Range/TransformView.h"

View 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

View File

@ -47,7 +47,6 @@ NAMESPACE_END(Range)
template <typename R>
using TRangeIterator = decltype(Range::Begin(DeclVal<R&>()));
NAMESPACE_BEGIN(Range)
/** @return The iterator to the end of a container. */
@ -212,6 +211,10 @@ NAMESPACE_END(Range)
/**
* A concept specifies a type is a range.
* A range is an iterator-sentinel pair that represents a sequence of elements.
* This concept does not require that iterator-sentinel pair can be fetched multiple times
* from the range object. again this means that const R may not be a range if R is a range,
* e.g. fetching the iterator-sentinel pair from the input range may require moving the iterator
* directly from the range object and thus the range object may be modified.
*/
template <typename R>
concept CRange =
@ -351,16 +354,16 @@ struct IContiguousRange /* : IRange<I, S> */
// Use IContiguousRange<...> represents a contiguous range type.
static_assert(CContiguousRange<IContiguousRange<IContiguousIterator<int&>>>);
/** A concept specifies a type is a range and its iterators and sentinel types are the same. */
/** A concept specifies a type is a range and its iterator and sentinel types are the same. */
template <typename R>
concept CCommonRange = CRange<R> && CSameAs<TRangeIterator<R>, TRangeSentinel<R>>;
/** This is an example of a common range type, indicate the traits that define a common range type. */
template <CForwardIterator I>
using TCommonRange = IRange<I, I>;
using ICommonRange = IRange<I, I>;
// Use TCommonRange<...> represents a common range type.
static_assert(CCommonRange<TCommonRange<IForwardIterator<int&>>>);
static_assert(CCommonRange<ICommonRange<IForwardIterator<int&>>>);
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)

View File

@ -0,0 +1,146 @@
#pragma once
#include "CoreTypes.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 helper class template for defining a view interface. Not directly instantiable. */
template <CClass T> requires (CSameAs<T, TRemoveCV<T>>)
class IBasicViewInterface
{
public:
/** @return The pointer to the underlying element storage. */
NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< T>) { return Range::GetData(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange<const T>) { return Range::GetData(static_cast<const T&>(*this)); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr auto Begin() requires (CRange< T>) { return Range::Begin(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto End() requires (CRange< T>) { return Range::End (static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange<const T>) { return Range::Begin(static_cast<const T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto End() const requires (CRange<const T>) { return Range::End (static_cast<const T&>(*this)); }
/** @return The reverse iterator to the first or end element. */
NODISCARD FORCEINLINE constexpr auto RBegin() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::RBegin(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto REnd() requires (CBidirectionalRange< T> && CCommonRange< T>) { return Range::REnd (static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto RBegin() const requires (CBidirectionalRange<const T> && CCommonRange<const T>) { return Range::RBegin(static_cast<const T&>(*this)); }
NODISCARD FORCEINLINE constexpr auto REnd() const requires (CBidirectionalRange<const T> && CCommonRange<const T>) { return Range::REnd (static_cast<const T&>(*this)); }
/** @return The number of elements in the container. */
NODISCARD FORCEINLINE constexpr size_t Num() requires (CSizedRange< T>) { return Range::Num(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange<const T>) { return Range::Num(static_cast<const T&>(*this)); }
/** @return true if the container is empty, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsEmpty() requires (CSizedRange< T> || CForwardRange< T>) { return Range::IsEmpty(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr bool IsEmpty() const requires (CSizedRange<const T> || CForwardRange<const T>) { return Range::IsEmpty(static_cast<const T&>(*this)); }
/** @return true if the container is empty, false otherwise. */
NODISCARD FORCEINLINE constexpr explicit operator bool() requires (CSizedRange< T> || CForwardRange< T>) { return !Range::IsEmpty(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr explicit operator bool() const requires (CSizedRange<const T> || CForwardRange<const T>) { return !Range::IsEmpty(static_cast<const T&>(*this)); }
/** @return The reference to the requested element. */
NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) requires (CRandomAccessRange< T>) { return Range::Begin(static_cast< T&>(*this))[Index]; }
NODISCARD FORCEINLINE constexpr decltype(auto) operator[](size_t Index) const requires (CRandomAccessRange<const T>) { return Range::Begin(static_cast<const T&>(*this))[Index]; }
/** @return The reference to the first or last element. */
NODISCARD FORCEINLINE constexpr decltype(auto) Front() requires (CForwardRange< T>) { return *Range::Begin(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr decltype(auto) Front() const requires (CForwardRange<const T>) { return *Range::Begin(static_cast<const T&>(*this)); }
NODISCARD FORCEINLINE constexpr decltype(auto) Back() requires (CBidirectionalRange< T> && CCommonRange< T>) { return *Range::RBegin(static_cast< T&>(*this)); }
NODISCARD FORCEINLINE constexpr decltype(auto) Back() const requires (CBidirectionalRange<const T> && CCommonRange<const T>) { return *Range::RBegin(static_cast<const T&>(*this)); }
ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT
private:
FORCEINLINE constexpr IBasicViewInterface() = default;
FORCEINLINE constexpr IBasicViewInterface(const IBasicViewInterface&) = default;
FORCEINLINE constexpr IBasicViewInterface(IBasicViewInterface&&) = default;
FORCEINLINE constexpr IBasicViewInterface& operator=(const IBasicViewInterface&) = default;
FORCEINLINE constexpr IBasicViewInterface& operator=(IBasicViewInterface&&) = default;
FORCEINLINE constexpr ~IBasicViewInterface() = default;
friend T;
};
NAMESPACE_END(Range)
/**
* A concept specifies that a range is a view, that is, it has constant time copy, move and assignment.
* Specify, a view can be movable only but not copyable, or it can be both movable and copyable.
*/
template <typename V>
concept CView = CRange<V> && CMovable<V> && CDerivedFrom<V, Range::IBasicViewInterface<TRemoveCVRef<V>>>;
NAMESPACE_PRIVATE_BEGIN
template <typename T> struct TIsInitializerList : FFalse { };
template <typename T> struct TIsInitializerList<initializer_list<T>> : FTrue { };
NAMESPACE_PRIVATE_END
/** A concept specifies that a viewable range that can be converted into a view through Range::All. */
template <typename R>
concept CViewableRange = CRange<R>
&& ((CView<TRemoveCVRef<R>> && CConstructibleFrom<TRemoveCVRef<R>, R>)
|| (!CView<TRemoveCVRef<R>> && (CLValueReference<R> || (CMovable<TRemoveReference<R>>
&& !NAMESPACE_PRIVATE::TIsInitializerList<TRemoveCVRef<R>>::Value))));
NAMESPACE_BEGIN(Range)
/** A simple view that combines an iterator-sentinel pair into a view. */
template <CInputOrOutputIterator I, CSentinelFor<I> S = I>
class TRangeView : public IBasicViewInterface<TRangeView<I, S>>
{
public:
using ElementType = TIteratorElementType<I>;
FORCEINLINE constexpr TRangeView() requires (CDefaultConstructible<I>) = default;
FORCEINLINE constexpr TRangeView(I InFirst, S InLast) : First(MoveTemp(InFirst)), Last(InLast) { }
NODISCARD FORCEINLINE constexpr I Begin() requires (!CCopyable<I>) { return MoveTemp(First); }
NODISCARD FORCEINLINE constexpr I Begin() const requires ( CCopyable<I>) { return First; }
NODISCARD FORCEINLINE constexpr S End() const { return Last; }
NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedSentinelFor<S, I>) { return Last - First; }
NODISCARD FORCEINLINE constexpr bool IsEmpty() const { return First == Last; }
private:
NO_UNIQUE_ADDRESS I First;
NO_UNIQUE_ADDRESS S Last;
};
template <CInputOrOutputIterator I, CSentinelFor<I> S>
TRangeView(I, S) -> TRangeView<I, S>;
NAMESPACE_END(Range)
template <typename I, typename S>
constexpr bool bEnableBorrowedRange<Range::TRangeView<I, S>> = true;
NAMESPACE_BEGIN(Range)
/** Creates A simple view that combines an iterator-sentinel pair. */
template <CInputOrOutputIterator I, CSentinelFor<I> S = I>
NODISCARD FORCEINLINE constexpr TRangeView<I, S> View(I First, S Last)
{
return TRangeView<I, S>(MoveTemp(First), Last);
}
NAMESPACE_END(Range)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END