#pragma once #include "CoreTypes.h" #include "Iterator/Utility.h" #include "Iterator/Sentinel.h" #include "Iterator/BidirectionalIterator.h" #include "Iterator/RandomAccessIterator.h" #include "Iterator/ContiguousIterator.h" #include "Miscellaneous/AssertionMacros.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) NAMESPACE_PRIVATE_BEGIN template class TCountedIteratorImpl { }; template class TCountedIteratorImpl { public: using ElementType = TIteratorElement; }; NAMESPACE_PRIVATE_END /** * An iterator adaptor that tracks the distance to the end of the range. * When based on an input or output iterator, the counted iterator satisfies at least an input or output iterator * up to a contiguous iterator. When based on an output iterator, the counted iterator satisfies an output iterator. * When based on iterator satisfies sentinel for itself, the counted iterator satisfies sized sentinel for itself. */ template class TCountedIterator final : public NAMESPACE_PRIVATE::TCountedIteratorImpl { public: using IteratorType = I; # 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; FORCEINLINE constexpr explicit TCountedIterator(IteratorType InValue, ptrdiff N) : Current(MoveTemp(InValue)) { 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 && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator& InValue) { Current = InValue.GetBase(); Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; } template requires (CCommonType) NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator& RHS) { return LHS.Length == RHS.Length; } template requires (CCommonType) 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 TIteratorReference operator*() { CheckThis(true); return *GetBase(); } NODISCARD FORCEINLINE constexpr TIteratorReference operator*() const requires (CDereferenceable) { CheckThis(true); return *GetBase(); } NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs>; }) { return ToAddress(GetBase()); } NODISCARD FORCEINLINE constexpr TIteratorReference operator[](ptrdiff Index) const requires (CRandomAccessIterator) { TCountedIterator Temp = *this + Index; return *Temp; } FORCEINLINE constexpr TCountedIterator& operator++() { ++Current; --Length; CheckThis(); return *this; } FORCEINLINE constexpr TCountedIterator& operator--() requires (CBidirectionalIterator) { --Current; ++Length; CheckThis(); return *this; } FORCEINLINE constexpr auto operator++(int) { --Length; CheckThis(); return Current++; } FORCEINLINE constexpr TCountedIterator operator++(int) requires (CForwardIterator) { TCountedIterator Temp = *this; ++Current; --Length; CheckThis(); return Temp; } FORCEINLINE constexpr TCountedIterator operator--(int) requires (CBidirectionalIterator) { TCountedIterator Temp = *this; --Current; ++Length; CheckThis(); return Temp; } FORCEINLINE constexpr TCountedIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; Length -= Offset; CheckThis(); return *this; } FORCEINLINE constexpr TCountedIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; Length += Offset; CheckThis(); return *this; } NODISCARD FORCEINLINE constexpr TCountedIterator operator+(ptrdiff Offset) const requires (CRandomAccessIterator) { TCountedIterator Temp = *this; Temp += Offset; return Temp; } NODISCARD FORCEINLINE constexpr TCountedIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { TCountedIterator Temp = *this; Temp -= Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(ptrdiff Offset, TCountedIterator Iter) requires (CRandomAccessIterator) { return Iter + Offset; } template requires (CCommonType) 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) { LHS.CheckThis(); return -LHS.Num(); } NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(FDefaultSentinel, const TCountedIterator& RHS) { RHS.CheckThis(); return RHS.Num(); } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { CheckThis(); return Current; } NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { CheckThis(); return MoveTemp(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( CInputIterator>>); static_assert( CForwardIterator>>); static_assert(CBidirectionalIterator>>); static_assert( CRandomAccessIterator>>); static_assert( CContiguousIterator>>); //static_assert(COutputIterator>, int>); static_assert(CSizedSentinelFor>, TCountedIterator>>); /** Creates a TCountedIterator of type inferred from the argument. */ template requires (CInputOrOutputIterator> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr auto MakeCountedIterator(I&& Iter, ptrdiff N) { return TCountedIterator>(Forward(Iter), N); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END