#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