From bc3cc3d2cc16b0712418901bf836281f2cc0fe06 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Tue, 21 Feb 2023 21:05:53 +0800 Subject: [PATCH] feat(containers): add helper functions like MakeReverseIterator() etc --- .../Source/Public/Containers/Iterator.h | 164 +++++++++++------- 1 file changed, 101 insertions(+), 63 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Containers/Iterator.h b/Redcraft.Utility/Source/Public/Containers/Iterator.h index b07e19d..ba206ab 100644 --- a/Redcraft.Utility/Source/Public/Containers/Iterator.h +++ b/Redcraft.Utility/Source/Public/Containers/Iterator.h @@ -3,6 +3,7 @@ #include "CoreTypes.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" +#include "Templates/Optional.h" #include "Templates/Noncopyable.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Compare.h" @@ -16,17 +17,9 @@ NAMESPACE_PRIVATE_BEGIN template using WithReference = T&; -template -struct TIteratorElementType -{ - using Type = typename I::ElementType; -}; +template struct TIteratorElementType { using Type = typename I::ElementType; }; -template -struct TIteratorElementType -{ - using Type = T; -}; +template struct TIteratorElementType { using Type = T; }; NAMESPACE_PRIVATE_END @@ -147,13 +140,13 @@ public: FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator&) = default; FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default; - template requires (!CSameAs> && CConstructibleFrom) + template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TReverseIterator(T&& InValue) : Current(Forward(InValue)) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(const TReverseIterator& InValue) : Current(InValue.GetBase()) { } - template requires (!CSameAs && CConstructibleFrom) + template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(TReverseIterator&& InValue) : Current(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) @@ -223,13 +216,13 @@ public: FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator&) = default; FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default; - template requires (!CSameAs> && CConstructibleFrom) + template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TMoveIterator(T&& InValue) : Current(Forward(InValue)) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(const TMoveIterator& InValue) : Current(InValue.GetBase()) { } - template requires (!CSameAs && CConstructibleFrom) + template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(TMoveIterator&& InValue) : Current(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) @@ -295,13 +288,13 @@ public: FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel&) = default; FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default; - template requires (!CSameAs> && CConstructibleFrom) + template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TMoveSentinel(T&& InValue) : Last(Forward(InValue)) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(const TMoveSentinel& InValue) : Last(InValue.GetBase()) { } - template requires (!CSameAs && CConstructibleFrom) + template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(TMoveSentinel&& InValue) : Last(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) @@ -371,13 +364,13 @@ public: FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator&) = default; FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default; - template requires (!CSameAs> && CConstructibleFrom) + template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TCountedIterator(T&& InValue, ptrdiff N) : Current(Forward(InValue)), Length(N) { check_code({ MaxLength = N; }); } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TCountedIterator(const TCountedIterator& InValue) : Current(InValue.GetBase()), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } - template requires (!CSameAs && CConstructibleFrom) + template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TCountedIterator(TCountedIterator&& InValue) : Current(MoveTemp(InValue).GetBase()), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) @@ -396,7 +389,9 @@ public: NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(FDefaultSentinel) const& { return static_cast(0) <=> Length; } + NODISCARD FORCEINLINE constexpr decltype(auto) operator*() { CheckThis(true); return *Current; } NODISCARD FORCEINLINE constexpr decltype(auto) operator*() const { CheckThis(true); return *Current; } + NODISCARD FORCEINLINE constexpr decltype(auto) operator->() { CheckThis(true); return AddressOf(operator*()); } NODISCARD FORCEINLINE constexpr decltype(auto) operator->() const { CheckThis(true); return AddressOf(operator*()); } NODISCARD FORCEINLINE constexpr decltype(auto) operator[](ptrdiff Index) const requires (CRandomAccessIterator) { TCountedIterator Temp = *this + Index; return *Temp; } @@ -454,53 +449,48 @@ static_assert(CSizedSentinelFor>); template TCountedIterator(I, ptrdiff) -> TCountedIterator; -template requires (CReferenceable> && CMovable && CMovable) -class TFunctionalInputIterator final : private FNoncopyable +/** An input iterator adapter that wraps a callable object. */ +template requires (CTOptional>> && CMoveConstructible + && CConstructibleFrom>, TInvokeResult> && CAssignableFrom>&, TInvokeResult>) +class TInputIterator final : private FNoncopyable { public: - using Inputer = F; - using Sentinel = G; + using Inputer = F; - using ElementType = TRemoveReference>; + using ElementType = typename TRemoveCVRef>::ValueType; - FORCEINLINE constexpr TFunctionalInputIterator() requires (CDefaultConstructible && CDefaultConstructible) : bIsConsumed(false) { }; + FORCEINLINE constexpr TInputIterator() requires (CDefaultConstructible) : LookAhead(Invoke(Storage)) { }; - template requires (CConstructibleFrom && CConstructibleFrom) - FORCEINLINE constexpr TFunctionalInputIterator(T&& InInputer, U&& InSentinel) : InputerStorage(Forward(InInputer)), SentinelStorage(Forward(InSentinel)), bIsConsumed(false) { } + template requires (!CSameAs> && CConstructibleFrom) + FORCEINLINE constexpr explicit TInputIterator(T&& InInputer) : Storage(Forward(InInputer)), LookAhead(Invoke(Storage)) { } - NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Invoke(SentinelStorage); } + NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return !LookAhead.IsValid(); } - NODISCARD FORCEINLINE constexpr decltype(auto) operator*() const { checkf(!bIsConsumed, TEXT("The element are consumed. Please check IsConsumed().")); bIsConsumed = true; return Invoke(InputerStorage); } - NODISCARD FORCEINLINE constexpr void operator->() const = delete; + NODISCARD FORCEINLINE constexpr const ElementType& operator*() const { return LookAhead.GetValue(); } - FORCEINLINE constexpr TFunctionalInputIterator& operator++() { if (!bIsConsumed) Invoke(InputerStorage); bIsConsumed = false; return *this; } + FORCEINLINE constexpr TInputIterator& operator++() { LookAhead = Invoke(Storage); return *this; } - FORCEINLINE constexpr void operator++(int) { if (!bIsConsumed) Invoke(InputerStorage); bIsConsumed = false; } + FORCEINLINE constexpr void operator++(int) { LookAhead = Invoke(Storage); } - NODISCARD FORCEINLINE constexpr const Inputer& GetInputer() const& { return InputerStorage; } - NODISCARD FORCEINLINE constexpr Inputer GetInputer() && { return InputerStorage; } - - NODISCARD FORCEINLINE constexpr const Sentinel& GetSentinel() const& { return SentinelStorage; } - NODISCARD FORCEINLINE constexpr Sentinel GetSentinel() && { return SentinelStorage; } - - NODISCARD FORCEINLINE constexpr bool IsConsumed() const { return bIsConsumed; } + NODISCARD FORCEINLINE constexpr const Inputer& GetInputer() const& { return Storage; } + NODISCARD FORCEINLINE constexpr Inputer GetInputer() && { return Storage; } private: - Inputer InputerStorage; - Sentinel SentinelStorage; - mutable bool bIsConsumed; + Inputer Storage; + TOptional LookAhead; }; -static_assert(CInputIterator>); +static_assert(CInputIterator(*)()>>); -template -TFunctionalInputIterator(F, G) -> TFunctionalInputIterator; +template +TInputIterator(F) -> TInputIterator; -template -class TFunctionalOutputIterator final : private FNoncopyable +/** An output iterator adapter that wraps a callable object. */ +template +class TOutputIterator final : private FNoncopyable { public: @@ -512,7 +502,7 @@ private: { public: - FORCEINLINE constexpr FIndirectionProxy(const TFunctionalOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } + FORCEINLINE constexpr FIndirectionProxy(TOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } # if DO_CHECK FORCEINLINE ~FIndirectionProxy() @@ -525,13 +515,13 @@ private: FORCEINLINE constexpr void operator=(T&& InValue) const { checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); - Invoke(Iter.OutputerStorage, Forward(InValue)); + Invoke(Iter.Storage, Forward(InValue)); check_code({ bIsProduced = true; }); } private: - const TFunctionalOutputIterator& Iter; + TOutputIterator& Iter; # if DO_CHECK mutable bool bIsProduced; @@ -543,7 +533,7 @@ private: { public: - FORCEINLINE constexpr FPostIncrementProxy(const TFunctionalOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } + FORCEINLINE constexpr FPostIncrementProxy(TOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } # if DO_CHECK FORCEINLINE ~FPostIncrementProxy() @@ -561,7 +551,7 @@ private: private: - const TFunctionalOutputIterator& Iter; + TOutputIterator& Iter; # if DO_CHECK mutable bool bIsProduced; @@ -571,19 +561,19 @@ private: public: - FORCEINLINE constexpr TFunctionalOutputIterator() requires (CDefaultConstructible) { check_code({ bIsProduced = false; }); } + FORCEINLINE constexpr TOutputIterator() requires (CDefaultConstructible) { check_code({ bIsProduced = false; }); } - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TFunctionalOutputIterator(T&& InOutputer) : OutputerStorage(Forward(InOutputer)) { check_code({ bIsProduced = false; }); } + template requires (!CSameAs> && CConstructibleFrom) + FORCEINLINE constexpr explicit TOutputIterator(T&& InOutputer) : Storage(Forward(InOutputer)) { check_code({ bIsProduced = false; }); } - NODISCARD FORCEINLINE constexpr FIndirectionProxy operator*() const + NODISCARD FORCEINLINE constexpr FIndirectionProxy operator*() { checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); check_code({ bIsProduced = true; }); return FIndirectionProxy(*this); } - FORCEINLINE constexpr TFunctionalOutputIterator& operator++() { check_code({ bIsProduced = false; }); return *this; } + FORCEINLINE constexpr TOutputIterator& operator++() { check_code({ bIsProduced = false; }); return *this; } FORCEINLINE constexpr FPostIncrementProxy operator++(int) { @@ -591,24 +581,72 @@ public: return FPostIncrementProxy(*this); } - NODISCARD FORCEINLINE constexpr const Outputer& GetOutputer() const& { return OutputerStorage; } - NODISCARD FORCEINLINE constexpr Outputer GetOutputer() && { return OutputerStorage; } + NODISCARD FORCEINLINE constexpr const Outputer& GetOutputer() const& { return Storage; } + NODISCARD FORCEINLINE constexpr Outputer GetOutputer() && { return Storage; } private: - Outputer OutputerStorage; + Outputer Storage; # if DO_CHECK - mutable bool bIsProduced; + bool bIsProduced; # endif }; -static_assert(CIndirectlyWritable, int32>); -static_assert(COutputIterator, int32>); +static_assert(COutputIterator, int32>); template -TFunctionalOutputIterator(F) -> TFunctionalOutputIterator; +TOutputIterator(F) -> TOutputIterator; + +/** Creates a TReverseIterator of type inferred from the argument. */ +template requires (CBidirectionalIterator> && CConstructibleFrom, I>) +NODISCARD FORCEINLINE constexpr TReverseIterator MakeReverseIterator(I&& Iter) +{ + return TReverseIterator>(Forward(Iter)); +} + +/** Creates a TMoveIterator of type inferred from the argument. */ +template requires (CInputIterator> && CConstructibleFrom, I>) +NODISCARD FORCEINLINE constexpr TMoveIterator MakeMoveIterator(I&& Iter) +{ + return TMoveIterator>(Forward(Iter)); +} + +/** Creates a TMoveSentinel of type inferred from the argument. */ +template requires (CSemiregular> && CConstructibleFrom, I>) +NODISCARD FORCEINLINE constexpr TMoveSentinel MakeMoveSentinel(I&& Iter) +{ + return TMoveSentinel>(Forward(Iter)); +} + +/** Creates a TCountedIterator of type inferred from the argument. */ +template requires (CInputOrOutputIterator> && CConstructibleFrom, I>) +NODISCARD FORCEINLINE constexpr TCountedIterator MakeCountedIterator(I&& Iter, ptrdiff N) +{ + return TCountedIterator>(Forward(Iter), N); +} + +/** Creates an iterator adapter inserted in the front of the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeFrontInserter(C& Container) +{ + return TOutputIterator([&Container](T&& A) { Container.PushFront(Forward(A)); }); +} + +/** Creates an iterator adapter inserted in the back of the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container) +{ + return TOutputIterator([&Container](T&& A) { Container.PushBack(Forward(A)); }); +} + +/** Creates an iterator adapter inserted in the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& InIter) +{ + return TOutputIterator([&Container, Iter = InIter](T&& A) mutable { Iter = Container.Insert(Iter, Forward(A)); }); +} NAMESPACE_BEGIN(Iteration)