184 lines
7.5 KiB
C++
184 lines
7.5 KiB
C++
#pragma once
|
|
|
|
#include "CoreTypes.h"
|
|
#include "Range/View.h"
|
|
#include "Range/Pipe.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));
|
|
}
|
|
|
|
/** Creates A view adapter that includes all elements of a range. */
|
|
NODISCARD FORCEINLINE constexpr auto All()
|
|
{
|
|
using FClosure = decltype([]<CViewableRange R> requires (requires { Range::All(DeclVal<R>()); }) (R&& Base)
|
|
{
|
|
return Range::All(Forward<R>(Base));
|
|
});
|
|
|
|
return TAdaptorClosure<FClosure>();
|
|
}
|
|
|
|
/** 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
|