diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/Range.h b/Redcraft.Utility/Source/Public/Miscellaneous/Range.h deleted file mode 100644 index 640919d..0000000 --- a/Redcraft.Utility/Source/Public/Miscellaneous/Range.h +++ /dev/null @@ -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 -using TRangeIteratorType = TRangeIterator; - -template -using TRangeSentinelType = TRangeSentinel; - -template -using TRangeElementType = TRangeElement; - -template -using TRangeReferenceType = TRangeReference; - -template -using TRangeRValueReferenceType = TRangeRValueReference; - -NAMESPACE_BEGIN(Range) - -/** A view adapter that references the elements of some other range. */ -template requires (CObject) -class TRefView : public IBasicViewInterface> -{ -public: - - using ElementType = TRangeElementType; - using Reference = TRangeReferenceType; - using Iterator = TRangeIteratorType; - using Sentinel = TRangeSentinelType; - - template requires (!CSameAs, TRefView> && CConvertibleTo && CLValueReference) - FORCEINLINE constexpr TRefView(T&& InRange) : Ptr(AddressOf(static_cast(Forward(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) { 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* Ptr) { Range::IsEmpty(*Ptr); }) { return Range::IsEmpty(*Ptr); } - - NODISCARD FORCEINLINE constexpr R& GetBase() const { return *Ptr; } - -private: - - R* Ptr; - -}; - -template -TRefView(R&) -> TRefView; - -static_assert(CContiguousRange>>); -static_assert( CCommonRange>>); -static_assert( CSizedRange>>); -static_assert( CView>>); - -NAMESPACE_END(Range) - -template -constexpr bool bEnableBorrowedRange> = true; - -NAMESPACE_BEGIN(Range) - -/** A view adapter that has unique ownership of a range. */ -template requires (CMovable && !NAMESPACE_PRIVATE::TIsInitializerList::Value) -class TOwningView : public IBasicViewInterface> -{ -public: - - using ElementType = TRangeElementType; - using Reference = TRangeReferenceType; - using Iterator = TRangeIteratorType; - using Sentinel = TRangeSentinelType; - - 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 Iterator Begin() { return Range::Begin(Base); } - NODISCARD FORCEINLINE constexpr Sentinel End() { return Range::End (Base); } - NODISCARD FORCEINLINE constexpr Iterator Begin() const requires (CRange) { return Range::Begin(Base); } - NODISCARD FORCEINLINE constexpr Sentinel 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(CContiguousRange>>); -static_assert( CCommonRange>>); -static_assert( CSizedRange>>); -static_assert( CView>>); - -NAMESPACE_END(Range) - -template -constexpr bool bEnableBorrowedRange> = bEnableBorrowedRange; - -NAMESPACE_BEGIN(Range) - -/** A view adapter that includes all elements of a range. */ -template -using TAllView = - TConditional>, TDecay, - TConditional, TRefView>, TOwningView>>>; - -/** A view adapter that consists of the elements of a range that satisfies a predicate. */ -template > Pred> requires (CView && CObject && CMoveConstructible) -class TFilterView : public IBasicViewInterface> -{ -private: - - class FSentinelImpl; - -public: - - using ElementType = TRangeElementType; - - using Reference = TRangeReferenceType; - - class Iterator; - - using Sentinel = TConditional, Iterator, FSentinelImpl>; - - FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible && CDefaultConstructible) = 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(GetPredicate(), *Iter)) break; - - ++Iter; - } - while (false); - - if constexpr (!CForwardRange) return MoveTemp(Iter); - - return Iter; - } - - NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); } - - NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { 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>; - - FORCEINLINE constexpr Iterator() requires (CDefaultConstructible>) = default; - - NODISCARD friend FORCEINLINE constexpr bool operator==(const Iterator& LHS, const Iterator& RHS) - { - return LHS.Current == RHS.Current; - } - - NODISCARD FORCEINLINE constexpr TRangeReferenceType operator*() const { return *Current; } - NODISCARD FORCEINLINE constexpr TRangeIteratorType operator->() const { return Current; } - - FORCEINLINE constexpr Iterator& operator++() - { - do ++Current; while (*this != Owner->End() && !InvokeResult(Owner->GetPredicate(), *Current)); - - return *this; - } - - FORCEINLINE constexpr Iterator& operator--() requires (CBidirectionalIterator>) - { - do --Current; while (!InvokeResult(Owner->GetPredicate(), *Current)); - - return *this; - } - - FORCEINLINE constexpr void operator++(int) { Current++; } - FORCEINLINE constexpr Iterator operator++(int) requires (CForwardIterator>) { return Iterator(Owner, Current++); } - FORCEINLINE constexpr Iterator operator--(int) requires (CBidirectionalIterator>) { return Iterator(Owner, Current--); } - - friend FORCEINLINE void IndirectlyCopy(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyCopyable , TRangeIteratorType>) { IndirectlyCopy(Iter.Current, Jter.Current); } - friend FORCEINLINE void IndirectlyMove(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlyMovable , TRangeIteratorType>) { IndirectlyMove(Iter.Current, Jter.Current); } - friend FORCEINLINE void IndirectlySwap(const Iterator& Iter, const Iterator& Jter) requires (CIndirectlySwappable, TRangeIteratorType>) { IndirectlySwap(Iter.Current, Jter.Current); } - - NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } - - private: - - TFilterView* Owner; - - NO_UNIQUE_ADDRESS TRangeIteratorType Current; - - FORCEINLINE constexpr Iterator(TFilterView& InOwner, TRangeIteratorType InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { } - - friend FSentinelImpl; - - friend TFilterView; - }; - -private: - - class FSentinelImpl final - { - public: - - FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible>) = default; - - NODISCARD FORCEINLINE constexpr bool operator==(const Iterator& InValue) const& { return Current == InValue.Current; } - - NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } - - private: - - TRangeSentinelType Current; - - FORCEINLINE constexpr FSentinelImpl(TFilterView& InOwner, TRangeSentinelType InCurrent) : Current(InCurrent) { } - - friend TFilterView; - }; - -}; - -template -TFilterView(R&&, Pred) -> TFilterView, Pred>; - -static_assert(CBidirectionalRange, decltype([](auto) { return true; })>>); -static_assert( CCommonRange, decltype([](auto) { return true; })>>); -static_assert( CView, decltype([](auto) { return true; })>>); - -/** A view adapter of a sequence that applies a transformation function to each element. */ -template requires (CView && CObject - && CRegularInvocable> && CReferenceable>>) -class TTransformView : public IBasicViewInterface> -{ -private: - - template class FIteratorImpl; - template class FSentinelImpl; - -public: - - using ElementType = TRemoveReference>>; - - FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible&& CDefaultConstructible) = default; - - FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { } - - NODISCARD FORCEINLINE constexpr FIteratorImpl Begin() - { - return FIteratorImpl(*this, Range::Begin(Base)); - } - - NODISCARD FORCEINLINE constexpr FIteratorImpl Begin() const - requires (CRange && CRegularInvocable>) - { - return FIteratorImpl(*this, Range::Begin(Base)); - } - - NODISCARD FORCEINLINE constexpr FSentinelImpl End() - { - return FSentinelImpl(*this, Range::End(Base)); - } - - NODISCARD FORCEINLINE constexpr FIteratorImpl End() requires (CCommonRange) - { - return FIteratorImpl(*this, Range::End(Base)); - } - - NODISCARD FORCEINLINE constexpr FSentinelImpl End() const - requires (CRange && CRegularInvocable>) - { - return FSentinelImpl(*this, Range::End(Base)); - } - - NODISCARD FORCEINLINE constexpr FIteratorImpl End() const - requires (CCommonRange && CRegularInvocable>) - { - return FIteratorImpl(*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 { return Range::Num(Base); } - - NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { return Base; } - NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } - -private: - - NO_UNIQUE_ADDRESS V Base; - NO_UNIQUE_ADDRESS F Func; - - template - class FIteratorImpl - { - private: - - using FOwner = TConditional; - using FBase = TConditional; - using FFunc = TConditional; - - public: - - using ElementType = TRemoveCVRef>>; - - FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible>) = default; - - FORCEINLINE constexpr FIteratorImpl(FIteratorImpl Iter) requires (bConst && CConvertibleTo, TRangeIteratorType>) - : Owner(Iter.Owner), Current(MoveTemp(Iter.Current)) - { } - - NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) - requires (CSentinelFor, TRangeIteratorType>) - { - return LHS.Current == RHS.Current; - } - - NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) - requires (CSizedSentinelFor, TRangeIteratorType>) - { - 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) { return Invoke(Owner->Func, Current[Index]); } - - FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; } - FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange) { --Current; return *this; } - - FORCEINLINE constexpr void operator++(int) { Current++; } - FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange) { return FIteratorImpl(Current++); } - FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange) { return FIteratorImpl(Current--); } - - FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) requires (CRandomAccessRange) { Current += Offset; return *this; } - FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) requires (CRandomAccessRange) { Current -= Offset; return *this; } - - NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(FIteratorImpl Iter, ptrdiff Offset) requires (CRandomAccessRange) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; } - NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, FIteratorImpl Iter) requires (CRandomAccessRange) { FIteratorImpl Temp = Iter; Temp += Offset; return Temp; } - - NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const requires (CRandomAccessRange) { FIteratorImpl Temp = *this; Temp -= Offset; return Temp; } - - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) - requires (CSizedSentinelFor, TRangeIteratorType>) - { - return LHS.Current - RHS.Current; - } - - NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } - - private: - - NO_UNIQUE_ADDRESS FOwner* Owner; - - NO_UNIQUE_ADDRESS TRangeIteratorType Current; - - FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIteratorType InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { } - - template friend class FIteratorImpl; - template friend class FSentinelImpl; - - friend TTransformView; - }; - - template - class FSentinelImpl - { - private: - - using FOwner = TConditional; - using FBase = TConditional; - - public: - - FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible>) = default; - - FORCEINLINE constexpr FSentinelImpl(FSentinelImpl Sentinel) requires (bConst && CConvertibleTo, TRangeSentinelType>) - : Current(Sentinel.Current) - { } - - NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Current == InValue.Current; } - - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FSentinelImpl& RHS) - requires CSizedSentinelFor, TRangeIteratorType> - { - return LHS.Current - RHS.Current; - } - - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl& RHS) - requires CSizedSentinelFor, TRangeIteratorType> - { - return RHS.Current - LHS.Current; - } - - NODISCARD FORCEINLINE constexpr const TRangeIteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr TRangeIteratorType GetBase() && { return MoveTemp(Current); } - - private: - - NO_UNIQUE_ADDRESS TRangeSentinelType Current; - - FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinelType InCurrent) : Current(InCurrent) { } - - friend TTransformView; - }; - -}; - -template -TTransformView(R&&, F) -> TTransformView, F>; - -static_assert(CRandomAccessRange, decltype([](auto) { return 0; })>>); -static_assert( CCommonRange, decltype([](auto) { return 0; })>>); -static_assert( CSizedRange, decltype([](auto) { return 0; })>>); -static_assert( CView, decltype([](auto) { return 0; })>>); - -NAMESPACE_END(Range) - -NAMESPACE_BEGIN(Range) - -/** Creates A view adapter that includes all elements of a range. */ -template -NODISCARD FORCEINLINE constexpr TAllView All(R&& InRange) -{ - return TAllView(Forward(InRange)); -} - -/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */ -template requires (requires { TFilterView(DeclVal(), DeclVal()); }) -NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate) -{ - return TFilterView(Forward(Base), Forward(Predicate)); -} - -/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */ -template -NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate) -{ - return [&Predicate](R&& Base) requires (requires { TFilterView(DeclVal(), DeclVal()); }) - { - return TFilterView(Forward(Base), Forward(Predicate)); - }; -} - -/** Creates A view adapter of a sequence that applies a transformation function to each element. */ -template requires (requires { TTransformView(DeclVal(), DeclVal()); }) -NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func) -{ - return TTransformView(Forward(Base), Forward(Func)); -} - -/** Creates A view adapter of a sequence that applies a transformation function to each element. */ -template -NODISCARD FORCEINLINE constexpr auto Transform(F&& Func) -{ - return [&Func](R&& Base) requires (requires { TTransformView(DeclVal(), DeclVal()); }) - { - return TTransformView(Forward(Base), Forward(Func)); - }; -} - -NAMESPACE_END(Range) - -template requires (CRange>) -NODISCARD FORCEINLINE constexpr auto operator|(R&& Range, T&& View) -{ - return Invoke(Forward(View), Forward(Range)); -} - -NAMESPACE_MODULE_END(Utility) -NAMESPACE_MODULE_END(Redcraft) -NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Range/AllView.h b/Redcraft.Utility/Source/Public/Range/AllView.h new file mode 100644 index 0000000..85f89d4 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Range/AllView.h @@ -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 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)); +} + +/** 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 diff --git a/Redcraft.Utility/Source/Public/Range/Factory.h b/Redcraft.Utility/Source/Public/Range/Factory.h index bb43074..8810bfa 100644 --- a/Redcraft.Utility/Source/Public/Range/Factory.h +++ b/Redcraft.Utility/Source/Public/Range/Factory.h @@ -250,8 +250,6 @@ private: NO_UNIQUE_ADDRESS FSizeType Count; -public: - class FIteratorImpl final { public: diff --git a/Redcraft.Utility/Source/Public/Range/FilterView.h b/Redcraft.Utility/Source/Public/Range/FilterView.h new file mode 100644 index 0000000..04d6af6 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Range/FilterView.h @@ -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 > Pred> requires (CView && CObject && CMoveConstructible) +class TFilterView : public IBasicViewInterface> +{ +private: + + class FIteratorImpl; + class FSentinelImpl; + +public: + + using ElementType = TRangeElement; + using Reference = TRangeReference; + + using Iterator = FIteratorImpl; + + using Sentinel = TConditional, FIteratorImpl, FSentinelImpl>; + + FORCEINLINE constexpr TFilterView() requires (CDefaultConstructible && CDefaultConstructible) = 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(GetPredicate(), *Iter)) break; + + ++Iter; + } + while (false); + + if constexpr (!CForwardRange) return MoveTemp(Iter); + + return Iter; + } + + NODISCARD FORCEINLINE constexpr Sentinel End() { return Sentinel(*this, Range::End(Base)); } + + NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { 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>; + + FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible>) { } // 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 operator*() const { return *GetBase(); } + + NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const TRangeIterator Iter) { { ToAddress(Iter) } -> CSameAs>>; }) { return ToAddress(GetBase()); } + + FORCEINLINE constexpr FIteratorImpl& operator++() + { + do ++Current; while (*this != Owner->End() && !InvokeResult(Owner->GetPredicate(), *Current)); + + return *this; + } + + FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalIterator>) + { + do --Current; while (!InvokeResult(Owner->GetPredicate(), *Current)); + + return *this; + } + + FORCEINLINE constexpr void operator++(int) { Current++; } + FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardIterator>) { return FIteratorImpl(Owner, Current++); } + FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalIterator>) { return FIteratorImpl(Owner, Current--); } + + NODISCARD FORCEINLINE constexpr const TRangeIterator& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr TRangeIterator GetBase() && { return MoveTemp(Current); } + + private: + + TFilterView* Owner; + + NO_UNIQUE_ADDRESS TRangeIterator Current; + + FORCEINLINE constexpr FIteratorImpl(TFilterView& InOwner, TRangeIterator 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& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr TRangeSentinel GetBase() && { return MoveTemp(Current); } + + private: + + TRangeSentinel Current; + + FORCEINLINE constexpr FSentinelImpl(TFilterView& InOwner, TRangeSentinel InCurrent) : Current(InCurrent) { } + + friend TFilterView; + }; + +}; + +template +TFilterView(R&&, Pred) -> TFilterView, Pred>; + +static_assert( CInputRange>>, bool(*)(int)>>); +static_assert( CForwardRange>>, bool(*)(int)>>); +static_assert(CBidirectionalRange>>, bool(*)(int)>>); +static_assert(CBidirectionalRange>>, bool(*)(int)>>); +static_assert(CBidirectionalRange>>, bool(*)(int)>>); + +static_assert(CCommonRange>>, bool(*)(int)>>); +static_assert( CView>>, 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 requires (requires { TFilterView(DeclVal(), DeclVal()); }) +NODISCARD FORCEINLINE constexpr auto Filter(R&& Base, Pred&& Predicate) +{ + return TFilterView(Forward(Base), Forward(Predicate)); +} + +/** Creates A view adapter that consists of the elements of a range that satisfies a predicate. */ +template +NODISCARD FORCEINLINE constexpr auto Filter(Pred&& Predicate) +{ + return [&Predicate] requires (requires { TFilterView(DeclVal(), DeclVal()); }) (R&& Base) + { + return TFilterView(Forward(Base), Forward(Predicate)); + }; +} + +NAMESPACE_END(Range) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Range/Range.h b/Redcraft.Utility/Source/Public/Range/Range.h index 781fd5b..2d9fd4d 100644 --- a/Redcraft.Utility/Source/Public/Range/Range.h +++ b/Redcraft.Utility/Source/Public/Range/Range.h @@ -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" diff --git a/Redcraft.Utility/Source/Public/Range/TransformView.h b/Redcraft.Utility/Source/Public/Range/TransformView.h new file mode 100644 index 0000000..fc20199 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Range/TransformView.h @@ -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 requires (CView && CObject + && CRegularInvocable> && CReferenceable>>) +class TTransformView : public IBasicViewInterface> +{ +private: + + template class FIteratorImpl; + template class FSentinelImpl; + +public: + + FORCEINLINE constexpr TTransformView() requires (CDefaultConstructible&& CDefaultConstructible) = default; + + FORCEINLINE constexpr explicit TTransformView(V InBase, F InFunc) : Base(MoveTemp(InBase)), Func(MoveTemp(InFunc)) { } + + NODISCARD FORCEINLINE constexpr auto Begin() + { + return FIteratorImpl(*this, Range::Begin(Base)); + } + + NODISCARD FORCEINLINE constexpr auto Begin() const requires (CRange && CRegularInvocable>) + { + return FIteratorImpl(*this, Range::Begin(Base)); + } + + NODISCARD FORCEINLINE constexpr auto End() + { + if constexpr (CCommonRange) + { + return FIteratorImpl(*this, Range::End(Base)); + } + + else return FSentinelImpl(*this, Range::End(Base)); + } + + NODISCARD FORCEINLINE constexpr auto End() const requires (CRange && CRegularInvocable>) + { + if constexpr (CCommonRange) + { + return FIteratorImpl(*this, Range::End(Base)); + } + + else return FSentinelImpl(*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) { return Range::Num(Base); } + + NODISCARD FORCEINLINE constexpr V GetBase() const& requires (CCopyConstructible) { return Base; } + NODISCARD FORCEINLINE constexpr V GetBase() && { return MoveTemp(Base); } + +private: + + NO_UNIQUE_ADDRESS V Base; + NO_UNIQUE_ADDRESS F Func; + + template + class FIteratorImpl + { + private: + + using FOwner = TConditional; + using FBase = TConditional; + using FFunc = TConditional; + + public: + + using ElementType = TRemoveCVRef>>; + + FORCEINLINE constexpr FIteratorImpl() requires (CDefaultConstructible>) = default; + + FORCEINLINE constexpr FIteratorImpl(FIteratorImpl Iter) requires (bConst && CConvertibleTo, TRangeIterator>) + : Owner(Iter.Owner), Current(MoveTemp(Iter).GetBase()) + { } + + NODISCARD friend FORCEINLINE constexpr bool operator==(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CEqualityComparable>) + { + return LHS.GetBase() == RHS.GetBase(); + } + + NODISCARD friend FORCEINLINE constexpr auto operator<=>(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CThreeWayComparable>) + { + 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) { return Invoke(Owner->Func, GetBase()[Index]); } + + FORCEINLINE constexpr FIteratorImpl& operator++() { ++Current; return *this; } + FORCEINLINE constexpr FIteratorImpl& operator--() requires (CBidirectionalRange) { --Current; return *this; } + + FORCEINLINE constexpr void operator++(int) { Current++; } + FORCEINLINE constexpr FIteratorImpl operator++(int) requires (CForwardRange) { return FIteratorImpl(Current++); } + FORCEINLINE constexpr FIteratorImpl operator--(int) requires (CBidirectionalRange) { return FIteratorImpl(Current--); } + + FORCEINLINE constexpr FIteratorImpl& operator+=(ptrdiff Offset) requires (CRandomAccessRange) { Current += Offset; return *this; } + FORCEINLINE constexpr FIteratorImpl& operator-=(ptrdiff Offset) requires (CRandomAccessRange) { Current -= Offset; return *this; } + + NODISCARD FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset) const requires (CRandomAccessRange) { FIteratorImpl Temp = *this; Temp += Offset; return Temp; } + NODISCARD FORCEINLINE constexpr FIteratorImpl operator-(ptrdiff Offset) const requires (CRandomAccessRange) { FIteratorImpl Temp = *this; Temp -= Offset; return Temp; } + + NODISCARD friend FORCEINLINE constexpr FIteratorImpl operator+(ptrdiff Offset, const FIteratorImpl& Iter) requires (CRandomAccessRange) { return Iter + Offset; } + + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FIteratorImpl& RHS) requires (CSizedSentinelFor, TRangeIterator>) + { + return LHS.GetBase() - RHS.GetBase(); + } + + NODISCARD FORCEINLINE constexpr const TRangeIterator& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr TRangeIterator GetBase() && { return MoveTemp(Current); } + + private: + + NO_UNIQUE_ADDRESS FOwner* Owner; + + NO_UNIQUE_ADDRESS TRangeIterator Current; + + FORCEINLINE constexpr FIteratorImpl(FOwner& InOwner, TRangeIterator InCurrent) : Owner(&InOwner), Current(MoveTemp(InCurrent)) { } + + template friend class FIteratorImpl; + template friend class FSentinelImpl; + + friend TTransformView; + }; + + template + class FSentinelImpl + { + private: + + using FOwner = TConditional; + using FBase = TConditional; + + public: + + FORCEINLINE constexpr FSentinelImpl() requires (CDefaultConstructible>) = default; + + FORCEINLINE constexpr FSentinelImpl(FSentinelImpl Sentinel) requires (bConst && CConvertibleTo, TRangeSentinel>) + : Current(Sentinel.GetBase()) + { } + + NODISCARD FORCEINLINE constexpr bool operator==(const FIteratorImpl& InValue) const& { return Current == InValue.GetBase(); } + + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FIteratorImpl& LHS, const FSentinelImpl& RHS) + requires CSizedSentinelFor, TRangeIterator> + { + return LHS.GetBase() - RHS.GetBase(); + } + + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const FSentinelImpl& LHS, const FIteratorImpl& RHS) + requires CSizedSentinelFor, TRangeIterator> + { + return RHS.GetBase() - LHS.GetBase(); + } + + NODISCARD FORCEINLINE constexpr const TRangeIterator& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr TRangeIterator GetBase() && { return MoveTemp(Current); } + + private: + + NO_UNIQUE_ADDRESS TRangeSentinel Current; + + FORCEINLINE constexpr FSentinelImpl(FOwner& InOwner, TRangeSentinel InCurrent) : Current(InCurrent) { } + + friend TTransformView; + }; + +}; + +template +TTransformView(R&&, F) -> TTransformView, F>; + +static_assert( CInputRange>>, int(*)(int)>>); +static_assert( CForwardRange>>, int(*)(int)>>); +static_assert(CBidirectionalRange>>, int(*)(int)>>); +static_assert( CRandomAccessRange>>, int(*)(int)>>); +static_assert( CRandomAccessRange>>, int(*)(int)>>); + +static_assert(CCommonRange>>, int(*)(int)>>); +static_assert( CSizedRange>>, int(*)(int)>>); +static_assert( CView>>, int(*)(int)>>); + +static_assert(COutputRange>>, 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 requires (requires { TTransformView(DeclVal(), DeclVal()); }) +NODISCARD FORCEINLINE constexpr auto Transform(R&& Base, F&& Func) +{ + return TTransformView(Forward(Base), Forward(Func)); +} + +/** Creates A view adapter of a sequence that applies a transformation function to each element. */ +template +NODISCARD FORCEINLINE constexpr auto Transform(F&& Func) +{ + return [&Func] requires (requires { TTransformView(DeclVal(), DeclVal()); }) (R&& Base) + { + return TTransformView(Forward(Base), Forward(Func)); + }; +} + +NAMESPACE_END(Range) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Range/View.h b/Redcraft.Utility/Source/Public/Range/View.h index 923902e..7757582 100644 --- a/Redcraft.Utility/Source/Public/Range/View.h +++ b/Redcraft.Utility/Source/Public/Range/View.h @@ -12,7 +12,7 @@ NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Range) /** A helper class template for defining a view interface. Not directly instantiable. */ -template requires (CClass && CSameAs>) +template requires (CSameAs>) class IBasicViewInterface { public: