#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 requires (CObject) class TRefView : public IBasicViewInterface> { private: // Use the function to check constructability. static void Func(R&); static void Func(R&&) = delete; public: template requires (!CSameAs, TRefView> && CConvertibleTo && requires { Func(DeclVal()); }) FORCEINLINE constexpr TRefView(T&& InRange) : Ptr(AddressOf(static_cast(Forward(InRange)))) { } NODISCARD FORCEINLINE constexpr TRangeIterator Begin() const { return Range::Begin(*Ptr); } NODISCARD FORCEINLINE constexpr TRangeSentinel End() const { return Range::End (*Ptr); } NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange) { return Range::GetData(*Ptr); } NODISCARD FORCEINLINE constexpr size_t Num() const requires (CSizedRange) { 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 TRefView(R&) -> TRefView; static_assert( CInputRange>>>); static_assert( CForwardRange>>>); static_assert(CBidirectionalRange>>>); static_assert( CRandomAccessRange>>>); static_assert( CContiguousRange>>>); static_assert(CCommonRange>>>); static_assert( CSizedRange>>>); static_assert( CView>>>); static_assert(COutputRange>>, int>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = 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 requires (CMovable && !NAMESPACE_PRIVATE::TIsInitializerList::Value) class TOwningView : public IBasicViewInterface> { public: FORCEINLINE constexpr TOwningView() requires (CDefaultConstructible) = 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) { return Range::Begin(Base); } NODISCARD FORCEINLINE constexpr auto End() const requires (CRange) { return Range::End (Base); } NODISCARD FORCEINLINE constexpr auto GetData() requires (CContiguousRange< R>) { return Range::GetData(Base); } NODISCARD FORCEINLINE constexpr auto GetData() const requires (CContiguousRange) { 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) { 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>>>); static_assert( CForwardRange>>>); static_assert(CBidirectionalRange>>>); static_assert( CRandomAccessRange>>>); static_assert( CContiguousRange>>>); static_assert(CCommonRange>>>); static_assert( CSizedRange>>>); static_assert( CView>>>); static_assert(COutputRange>>, int>); NAMESPACE_END(Range) template constexpr bool bEnableBorrowedRange> = bEnableBorrowedRange; NAMESPACE_BEGIN(Range) /** Creates A view adapter that includes all elements of a range. */ template NODISCARD FORCEINLINE constexpr auto All(R&& InRange) { if constexpr (CView>) { return TDecay(Forward(InRange)); } else if constexpr (requires { TRefView(Forward(InRange)); }) { return TRefView(Forward(InRange)); } else return TOwningView(Forward(InRange)); } /** Creates A view adapter that includes all elements of a range. */ NODISCARD FORCEINLINE constexpr auto All() { using FClosure = decltype([] requires (requires { Range::All(DeclVal()); }) (R&& Base) { return Range::All(Forward(Base)); }); return TAdaptorClosure(); } /** A view adapter that includes all elements of a range. */ template using TAllView = decltype(Range::All(DeclVal())); static_assert( CInputRange>>>); static_assert( CForwardRange>>>); static_assert(CBidirectionalRange>>>); static_assert( CRandomAccessRange>>>); static_assert( CContiguousRange>>>); static_assert(CCommonRange>>>); static_assert( CSizedRange>>>); static_assert( CView>>>); static_assert(COutputRange>>, int>); NAMESPACE_END(Range) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END