diff --git a/Redcraft.Utility/Source/Public/Containers/Iterator.h b/Redcraft.Utility/Source/Public/Containers/Iterator.h index b5d4300..99f3280 100644 --- a/Redcraft.Utility/Source/Public/Containers/Iterator.h +++ b/Redcraft.Utility/Source/Public/Containers/Iterator.h @@ -1,7 +1,9 @@ #pragma once #include "CoreTypes.h" +#include "Templates/Invoke.h" #include "Templates/Utility.h" +#include "Templates/Noncopyable.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Compare.h" #include "Miscellaneous/AssertionMacros.h" @@ -35,17 +37,17 @@ template concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; }; template -using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType::Type; +using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType>::Type; template using TIteratorReferenceType = decltype(*DeclVal()); -template requires (requires(T& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) -using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal())); +template requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) +using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal())); template concept CIndirectlyReadable = - requires(const I Iter) + requires(const TRemoveCVRef Iter) { typename TIteratorElementType; typename TIteratorReferenceType; @@ -59,7 +61,7 @@ concept CIndirectlyReadable = template concept CIndirectlyWritable = - requires(I && Iter, T && A) + requires(I&& Iter, T&& A) { *Iter = Forward(A); *Forward(Iter) = Forward(A); @@ -68,7 +70,7 @@ concept CIndirectlyWritable = }; template -concept CWeaklyIncrementable = CDefaultConstructible && CMovable +concept CWeaklyIncrementable = CMovable && requires(I Iter) { { ++Iter } -> CSameAs; Iter++; }; template @@ -180,7 +182,8 @@ public: NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() - LHS.GetBase(); } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() const { return Current; } + NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return Current; } private: @@ -249,7 +252,8 @@ public: NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() - RHS.GetBase(); } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() const { return Current; } + NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return Current; } private: @@ -297,7 +301,8 @@ public: template requires (CSizedSentinelFor) NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); } - NODISCARD FORCEINLINE constexpr SentinelType GetBase() const { return Last; } + NODISCARD FORCEINLINE constexpr const SentinelType& GetBase() const& { return Last; } + NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return Last; } private: @@ -391,8 +396,9 @@ public: NODISCARD FORCEINLINE constexpr explicit operator ElementType*() requires (CContiguousIterator && !CConst) { CheckThis(); return Current; } NODISCARD FORCEINLINE constexpr explicit operator const ElementType*() const requires (CContiguousIterator) { CheckThis(); return Current; } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() const { CheckThis(); return Current; } - NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; } + NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; } + NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return Current; } + NODISCARD FORCEINLINE constexpr ptrdiff Num() const { CheckThis(); return Length; } private: @@ -417,6 +423,57 @@ private: static_assert(CContiguousIterator>); static_assert(CSizedSentinelFor>); +template +TCountedIterator(I, ptrdiff) -> TCountedIterator; + +template requires (CReferenceable> && CBooleanTestable> && CMovable && CMovable) +class TFunctionalInputIterator final : private FNoncopyable +{ +public: + + using Inputer = F; + using Sentinel = G; + + using ElementType = TRemoveReference>; + + FORCEINLINE constexpr TFunctionalInputIterator() = default; + + FORCEINLINE constexpr TFunctionalInputIterator(TFunctionalInputIterator&&) = default; + FORCEINLINE constexpr TFunctionalInputIterator& operator=(TFunctionalInputIterator&&) = default; + + template requires (CConvertibleTo && CConvertibleTo) + FORCEINLINE constexpr TFunctionalInputIterator(T&& InInputer, U&& InSentinel) : InputerStorage(Forward(InInputer)), SentinelStorage(Forward(InSentinel)), bIsConsumed(false) { } + + NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Invoke(SentinelStorage); } + + 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; + + FORCEINLINE constexpr TFunctionalInputIterator& operator++() { if (!bIsConsumed) Invoke(InputerStorage); bIsConsumed = false; return *this; } + + FORCEINLINE constexpr void operator++(int) { if (!bIsConsumed) Invoke(InputerStorage); bIsConsumed = false; } + + 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; } + +private: + + Inputer InputerStorage; + Sentinel SentinelStorage; + mutable bool bIsConsumed; + +}; + +static_assert(CInputIterator>); + +template +TFunctionalInputIterator(F, G) -> TFunctionalInputIterator; + NAMESPACE_BEGIN(Iteration) /** Increments given iterator 'Iter' by 'N' elements. */