From 07c826fe86dc05eb667b083c331ff294467480dd Mon Sep 17 00:00:00 2001 From: Redstone1024 <2824517378@qq.com> Date: Mon, 28 Oct 2024 17:49:50 +0800 Subject: [PATCH] feat(miscellaneous): add TConstantIterator --- .../Public/Miscellaneous/ConstantIterator.h | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 Redcraft.Utility/Source/Public/Miscellaneous/ConstantIterator.h diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/ConstantIterator.h b/Redcraft.Utility/Source/Public/Miscellaneous/ConstantIterator.h new file mode 100644 index 0000000..2abb58b --- /dev/null +++ b/Redcraft.Utility/Source/Public/Miscellaneous/ConstantIterator.h @@ -0,0 +1,222 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/Utility.h" +#include "Containers/Iterator.h" +#include "Miscellaneous/Compare.h" +#include "TypeTraits/TypeTraits.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +/** An iterator that always points to the same value. */ +template requires (CDestructible || CLValueReference) +class TConstantIterator final +{ +public: + + using ElementType = T; + + FORCEINLINE constexpr TConstantIterator() = default; + + FORCEINLINE constexpr ~TConstantIterator() = default; + + template requires (!CSameAs> && CConstructibleFrom) + FORCEINLINE constexpr explicit TConstantIterator(U&& InValue) : Value(Forward(InValue)) { } + + template requires (CConstructibleFrom) + FORCEINLINE constexpr explicit (!CConvertibleTo) TConstantIterator(const TConstantIterator& InValue) : Value(InValue.Value) { } + + template requires (CConstructibleFrom) + FORCEINLINE constexpr explicit (!CConvertibleTo) TConstantIterator(TConstantIterator&& InValue) : Value(MoveTemp(InValue.Value)) { } + + FORCEINLINE constexpr TConstantIterator(const TConstantIterator&) requires (CCopyConstructible) = default; + + FORCEINLINE constexpr TConstantIterator(TConstantIterator&&) requires (CMoveConstructible) = default; + + template requires (CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator& InValue) { Value = InValue.Value; return *this; } + + template requires (CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&& InValue) { Value = MoveTemp(InValue.Value); return *this; } + + FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator&) requires (CCopyAssignable) = default; + + FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&&) requires (CMoveAssignable) = default; + + NODISCARD FORCEINLINE constexpr const T& operator*() const { return Value; } + + FORCEINLINE constexpr TConstantIterator& operator++() { return *this; } + + FORCEINLINE constexpr void operator++(int) { } + +private: + + T Value; + + template requires (CDestructible || CLValueReference) + friend class TConstantIterator; + +}; + +static_assert(CInputIterator>); + +/** An iterator that always points to the same value. */ +template +class TConstantIterator final +{ +public: + + using ElementType = T; + + FORCEINLINE constexpr TConstantIterator() = default; + + FORCEINLINE constexpr TConstantIterator(const TConstantIterator&) = default; + FORCEINLINE constexpr TConstantIterator(TConstantIterator&&) = default; + FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator&) = default; + FORCEINLINE constexpr TConstantIterator& operator=(TConstantIterator&&) = default; + + FORCEINLINE constexpr ~TConstantIterator() = default; + + FORCEINLINE constexpr explicit TConstantIterator(const T& InValue) : Ptr(AddressOf(InValue)) { } + + FORCEINLINE constexpr explicit TConstantIterator(const T&& InValue) = delete; + + template requires (CConvertibleTo) + FORCEINLINE constexpr TConstantIterator(const TConstantIterator& InValue) : Ptr(InValue.Ptr) { } + + template requires (CConvertibleTo) + FORCEINLINE constexpr TConstantIterator& operator=(const TConstantIterator& InValue) { Ptr = InValue.Ptr; return *this; } + + NODISCARD FORCEINLINE constexpr const T& operator*() const { return *Ptr; } + + FORCEINLINE constexpr TConstantIterator& operator++() { return *this; } + + FORCEINLINE constexpr void operator++(int) { } + +private: + + const T* Ptr; + + template requires (CDestructible || CLValueReference) + friend class TConstantIterator; + +}; + +static_assert(CInputIterator>); + +/** An iterator adapter specialization that tracks the distance of a constant iterator to the end of the range. */ +template requires (CDestructible || CLValueReference) +class TCountedIterator> final +{ +public: + + using IteratorType = TConstantIterator; + + using ElementType = typename TConstantIterator::ElementType; + +# if DO_CHECK + FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible) : Length(1), MaxLength(0) { } +# else + FORCEINLINE constexpr TCountedIterator() requires (CDefaultConstructible) = default; +# endif + + FORCEINLINE constexpr TCountedIterator(const TCountedIterator&) = default; + FORCEINLINE constexpr TCountedIterator(TCountedIterator&&) = default; + FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator&) = default; + FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&&) = default; + + FORCEINLINE constexpr ~TCountedIterator() = default; + + template requires (!CSameAs> && CConstructibleFrom) + FORCEINLINE constexpr explicit TCountedIterator(U&& 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) + FORCEINLINE constexpr explicit (!CConvertibleTo) TCountedIterator(TCountedIterator&& InValue) : Current(MoveTemp(InValue).GetBase()), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator& InValue) { Current = InValue.GetBase(); Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&& InValue) { Current = MoveTemp(InValue).GetBase(); Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; } + + template J> + NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator& RHS) { return LHS.Length == RHS.Length; } + + template J> + NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TCountedIterator& LHS, const TCountedIterator& RHS) { return LHS.Length <=> RHS.Length; } + + NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return Length == static_cast(0); } + + NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(FDefaultSentinel) const& { return static_cast(0) <=> Length; } + + NODISCARD FORCEINLINE constexpr const TRemoveReference& operator*() const { CheckThis(true); return *Current; } + NODISCARD FORCEINLINE constexpr const TRemoveReference* operator->() const { CheckThis(true); return AddressOf(operator*()); } + + NODISCARD FORCEINLINE constexpr const TRemoveReference& operator[](ptrdiff) const { return *this; } + + FORCEINLINE constexpr TCountedIterator& operator++() { --Length; CheckThis(); return *this; } + FORCEINLINE constexpr TCountedIterator& operator--() { ++Length; CheckThis(); return *this; } + + FORCEINLINE constexpr TCountedIterator operator++(int) { TCountedIterator Temp = *this; --Length; CheckThis(); return Temp; } + FORCEINLINE constexpr TCountedIterator operator--(int) { TCountedIterator Temp = *this; ++Length; CheckThis(); return Temp; } + + FORCEINLINE constexpr TCountedIterator& operator+=(ptrdiff Offset) { Length -= Offset; CheckThis(); return *this; } + FORCEINLINE constexpr TCountedIterator& operator-=(ptrdiff Offset) { Length += Offset; CheckThis(); return *this; } + + NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(TCountedIterator Iter, ptrdiff Offset) { TCountedIterator Temp = Iter; Temp += Offset; return Temp; } + NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(ptrdiff Offset, TCountedIterator Iter) { TCountedIterator Temp = Iter; Temp += Offset; return Temp; } + + NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const { TCountedIterator Temp = *this; Temp -= Offset; return Temp; } + + template J> + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Length - RHS.Length; } + + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TCountedIterator& LHS, FDefaultSentinel) { CheckThis(); return -LHS.Num(); } + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { CheckThis(); return RHS.Num(); } + + 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: + + IteratorType Current; + ptrdiff Length; + +# if DO_CHECK + ptrdiff MaxLength; +# endif + + FORCEINLINE void CheckThis(bool bExceptEnd = false) const + { + checkf(static_cast(0) <= Length && Length <= MaxLength, TEXT("Read access violation. Please check Num().")); + checkf(!(bExceptEnd && Length == static_cast(0)), TEXT("Read access violation. Please check Num().")); + } + + template + friend class TCountedIterator; + +}; + +static_assert(CRandomAccessIterator>>); + +template requires (CDestructible || CLValueReference) +NODISCARD FORCEINLINE constexpr auto MakeConstantIterator(T&& Value) +{ + return TConstantIterator(Forward(Value)); +} + +template requires (CDestructible || CLValueReference) +NODISCARD FORCEINLINE constexpr auto MakeCountedConstantIterator(T&& Value, ptrdiff N) +{ + return TCountedIterator>(MakeConstantIterator(Forward(Value)), N); +} + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END