#pragma once #include "CoreTypes.h" #include "Iterator/Utility.h" #include "Iterator/Sentinel.h" #include "Iterator/BasicIterator.h" #include "Miscellaneous/Compare.h" #include "TypeTraits/TypeTraits.h" #include "Templates/Utility.h" #include "Memory/Address.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) /** * An iterator adaptor which dereferences to a rvalue reference. * When based on at least an input iterator, the move iterator satisfies at least an input iterator * up to a random access iterator. */ template class TMoveIterator final { public: using FIteratorType = I; using FElementType = TIteratorElement; FORCEINLINE constexpr TMoveIterator() requires (CDefaultConstructible) = default; FORCEINLINE constexpr TMoveIterator(const TMoveIterator&) = default; FORCEINLINE constexpr TMoveIterator(TMoveIterator&&) = default; FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator&) = default; FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&&) = default; FORCEINLINE constexpr ~TMoveIterator() = default; FORCEINLINE constexpr explicit TMoveIterator(FIteratorType InValue) : Current(MoveTemp(InValue)) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(const TMoveIterator& InValue) : Current(InValue.GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.GetBase(); return *this; } template requires (CEqualityComparable) NODISCARD friend FORCEINLINE constexpr bool operator==(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() == RHS.GetBase(); } template requires (CThreeWayComparable) NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() <=> RHS.GetBase(); } NODISCARD FORCEINLINE constexpr TIteratorRValueReference operator*() const { return MoveTemp(*GetBase()); } NODISCARD FORCEINLINE constexpr TIteratorRValueReference operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return MoveTemp(GetBase()[Index]); } FORCEINLINE constexpr TMoveIterator& operator++() { ++Current; return *this; } FORCEINLINE constexpr TMoveIterator& operator--() requires (CBidirectionalIterator) { --Current; return *this; } FORCEINLINE constexpr void operator++(int) { Current++; } FORCEINLINE constexpr TMoveIterator operator++(int) requires (CForwardIterator) { return TMoveIterator(Current++); } FORCEINLINE constexpr TMoveIterator operator--(int) requires (CBidirectionalIterator) { return TMoveIterator(Current--); } FORCEINLINE constexpr TMoveIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; return *this; } FORCEINLINE constexpr TMoveIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; return *this; } NODISCARD FORCEINLINE constexpr TMoveIterator operator+(ptrdiff Offset) const requires (CRandomAccessIterator) { TMoveIterator Temp = *this; Temp += Offset; return Temp; } NODISCARD FORCEINLINE constexpr TMoveIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { TMoveIterator Temp = *this; Temp -= Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(ptrdiff Offset, const TMoveIterator& Iter) requires (CRandomAccessIterator) { return Iter + Offset; } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor) { return LHS.GetBase() - RHS.GetBase(); } NODISCARD FORCEINLINE constexpr const FIteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr FIteratorType GetBase() && { return MoveTemp(Current); } private: FIteratorType Current; }; template requires (!CSizedSentinelFor) inline constexpr bool bDisableSizedSentinelFor, TMoveIterator> = true; static_assert( CInputIterator>>); static_assert( CForwardIterator>>); static_assert(CBidirectionalIterator>>); static_assert( CRandomAccessIterator>>); static_assert( CRandomAccessIterator>>); /** * A sentinel adaptor for use with TMoveIterator. * Whether based on un-sized or sized sentinel, the move sentinel satisfies the corresponding concept. */ template class TMoveSentinel { public: using FSentinelType = S; FORCEINLINE constexpr TMoveSentinel() = default; FORCEINLINE constexpr TMoveSentinel(const TMoveSentinel&) = default; FORCEINLINE constexpr TMoveSentinel(TMoveSentinel&&) = default; FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel&) = default; FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&&) = default; FORCEINLINE constexpr ~TMoveSentinel() = default; FORCEINLINE constexpr explicit TMoveSentinel(FSentinelType InValue) : Last(InValue) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(const TMoveSentinel& InValue) : Last(InValue.Last) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel& InValue) { Last = InValue.GetBase(); return *this; } template requires (CSentinelFor) NODISCARD FORCEINLINE constexpr bool operator==(const TMoveIterator& InValue) const& { return GetBase() == InValue.GetBase(); } template requires (CSizedSentinelFor) NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveSentinel& Sentinel, const TMoveIterator& Iter) { return Sentinel.GetBase() - Iter.GetBase(); } template requires (CSizedSentinelFor) NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& Iter, const TMoveSentinel& Sentinel) { return Iter.GetBase() - Sentinel.GetBase(); } NODISCARD FORCEINLINE constexpr const FSentinelType& GetBase() const& { return Last; } NODISCARD FORCEINLINE constexpr FSentinelType GetBase() && { return MoveTemp(Last); } private: FSentinelType Last; }; static_assert( CSentinelFor>>, TMoveIterator>>); static_assert(CSizedSentinelFor>>, TMoveIterator>>); /** Creates a TMoveIterator of type inferred from the argument. */ template requires (CInputIterator> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr auto MakeMoveIterator(I&& Iter) { return TMoveIterator>(Forward(Iter)); } /** Creates a TMoveSentinel of type inferred from the argument. */ template requires (CSemiregular> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr auto MakeMoveSentinel(I&& Iter) { return TMoveSentinel>(Forward(Iter)); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END