diff --git a/Redcraft.Utility/Source/Public/Containers/Array.h b/Redcraft.Utility/Source/Public/Containers/Array.h index ef2f752..b511ef7 100644 --- a/Redcraft.Utility/Source/Public/Containers/Array.h +++ b/Redcraft.Utility/Source/Public/Containers/Array.h @@ -125,7 +125,7 @@ public: NODISCARD FORCEINLINE constexpr ElementType& operator*() const { CheckThis(true); return *Pointer; } NODISCARD FORCEINLINE constexpr ElementType* operator->() const { CheckThis(true); return Pointer; } - NODISCARD FORCEINLINE constexpr ElementType& operator[](ptrdiff Index) const { TArrayIterator Temp = *this + Index; Temp.CheckThis(); return *Temp; } + NODISCARD FORCEINLINE constexpr ElementType& operator[](ptrdiff Index) const { TArrayIterator Temp = *this + Index; return *Temp; } FORCEINLINE constexpr TArrayIterator& operator++() { ++Pointer; CheckThis(); return *this; } FORCEINLINE constexpr TArrayIterator& operator--() { --Pointer; CheckThis(); return *this; } @@ -136,21 +136,15 @@ public: FORCEINLINE constexpr TArrayIterator& operator+=(ptrdiff Offset) { Pointer += Offset; CheckThis(); return *this; } FORCEINLINE constexpr TArrayIterator& operator-=(ptrdiff Offset) { Pointer -= Offset; CheckThis(); return *this; } - NODISCARD friend FORCEINLINE constexpr TArrayIterator operator+(TArrayIterator Iter, ptrdiff Offset) { TArrayIterator Temp = Iter; Temp += Offset; Temp.CheckThis(); return Temp; } - NODISCARD friend FORCEINLINE constexpr TArrayIterator operator+(ptrdiff Offset, TArrayIterator Iter) { TArrayIterator Temp = Iter; Temp += Offset; Temp.CheckThis(); return Temp; } + NODISCARD friend FORCEINLINE constexpr TArrayIterator operator+(TArrayIterator Iter, ptrdiff Offset) { TArrayIterator Temp = Iter; Temp += Offset; return Temp; } + NODISCARD friend FORCEINLINE constexpr TArrayIterator operator+(ptrdiff Offset, TArrayIterator Iter) { TArrayIterator Temp = Iter; Temp += Offset; return Temp; } - NODISCARD FORCEINLINE constexpr TArrayIterator operator-(ptrdiff Offset) const { TArrayIterator Temp = *this; Temp -= Offset; Temp.CheckThis(); return Temp; } + NODISCARD FORCEINLINE constexpr TArrayIterator operator-(ptrdiff Offset) const { TArrayIterator Temp = *this; Temp -= Offset; return Temp; } - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TArrayIterator& LHS, const TArrayIterator& RHS) - { - LHS.CheckThis(); - RHS.CheckThis(); + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TArrayIterator& LHS, const TArrayIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.Pointer - RHS.Pointer; } - return LHS.Pointer - RHS.Pointer; - } - - NODISCARD FORCEINLINE constexpr explicit operator ElementType*() requires (!CConst) { return Pointer; } - NODISCARD FORCEINLINE constexpr explicit operator const ElementType*() const { return Pointer; } + NODISCARD FORCEINLINE constexpr explicit operator ElementType*() requires (!CConst) { CheckThis(); return Pointer; } + NODISCARD FORCEINLINE constexpr explicit operator const ElementType*() const { CheckThis(); return Pointer; } private: diff --git a/Redcraft.Utility/Source/Public/Containers/Iterator.h b/Redcraft.Utility/Source/Public/Containers/Iterator.h index cac6f55..b5d4300 100644 --- a/Redcraft.Utility/Source/Public/Containers/Iterator.h +++ b/Redcraft.Utility/Source/Public/Containers/Iterator.h @@ -153,11 +153,11 @@ public: template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.GetBase(); return *this; } - template requires (CWeaklyEqualityComparable) + template requires (CSentinelFor) NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator& RHS) { return LHS.GetBase() == RHS.GetBase(); } - template requires (CThreeWayComparable) - NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() <=> LHS.GetBase(); } + template requires (CSizedSentinelFor) + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() <=> LHS.GetBase(); } NODISCARD FORCEINLINE constexpr ElementType& operator*() const { IteratorType Temp = GetBase(); return *--Temp; } NODISCARD FORCEINLINE constexpr ElementType* operator->() const { return AddressOf(operator*()); } @@ -176,10 +176,9 @@ public: NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(TReverseIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp -= Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, TReverseIterator Iter) requires (CRandomAccessIterator) { TReverseIterator Temp = Iter; Temp -= Offset; return Temp; } - NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { return TReverseIterator(GetBase() + Offset); } + NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { TReverseIterator Temp = *this; Temp += Offset; return Temp; } - template requires (requires(IteratorType Iter, J Jter) { { Iter - Jter } -> CSameAs; }) - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.GetBase() - LHS.GetBase(); } + 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; } @@ -197,9 +196,7 @@ TReverseIterator(I) -> TReverseIterator; template requires (!CSizedSentinelFor) inline constexpr bool bDisableSizedSentinelFor, TReverseIterator> = true; -template -class TMoveSentinel; - +/** An iterator adaptor which dereferences to an rvalue reference. */ template class TMoveIterator final { @@ -224,21 +221,21 @@ public: template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.GetBase(); return *this; } - template requires (CWeaklyEqualityComparable) + template requires (CSentinelFor) 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(); } + template requires (CSizedSentinelFor) + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() <=> RHS.GetBase(); } NODISCARD FORCEINLINE constexpr ElementType&& operator*() const { return MoveTemp(*GetBase()); } NODISCARD FORCEINLINE constexpr ElementType* operator->() const = delete; - NODISCARD FORCEINLINE constexpr ElementType&& operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return MoveTemp(GetBase()[Index]); } + NODISCARD FORCEINLINE constexpr ElementType&& 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) { return TMoveIterator(Current++); } + 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--); } @@ -248,10 +245,9 @@ public: NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(TMoveIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TMoveIterator Temp = Iter; Temp += Offset; return Temp; } NODISCARD friend FORCEINLINE constexpr TMoveIterator operator+(ptrdiff Offset, TMoveIterator Iter) requires (CRandomAccessIterator) { TMoveIterator Temp = Iter; Temp += Offset; return Temp; } - NODISCARD FORCEINLINE constexpr TMoveIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { return TMoveIterator(GetBase() - Offset); } + NODISCARD FORCEINLINE constexpr TMoveIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { TMoveIterator Temp = *this; Temp -= Offset; return Temp; } - template requires (requires(IteratorType Iter, J Jter) { { Iter - Jter } -> CSameAs; }) - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.GetBase() - RHS.GetBase(); } + 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; } @@ -266,6 +262,7 @@ static_assert(CRandomAccessIterator>); template TMoveIterator(I) -> TMoveIterator; +/** A sentinel adaptor for use with TMoveIterator. */ template class TMoveSentinel { @@ -313,6 +310,113 @@ static_assert(CSizedSentinelFor, TMoveIterator>); template TMoveSentinel(I) -> TMoveSentinel; +struct FDefaultSentinel { explicit FDefaultSentinel() = default; }; + +inline constexpr FDefaultSentinel DefaultSentinel{ }; + +struct FUnreachableSentinel +{ + explicit FUnreachableSentinel() = default; + + template + NODISCARD FORCEINLINE constexpr bool operator==(const I&) const& { return false; } +}; + +inline constexpr FUnreachableSentinel UnreachableSentinel{ }; + +/** An iterator adaptor that tracks the distance to the end of the range. */ +template +class TCountedIterator final +{ +public: + + using IteratorType = I; + + using ElementType = TIteratorElementType; + +# 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 explicit TCountedIterator(IteratorType InValue, ptrdiff N) : Current(InValue), Length(N) { check_code({ MaxLength = N; }); } + + template requires (!CSameAs && CConvertibleTo) + FORCEINLINE constexpr TCountedIterator(const TCountedIterator& InValue) : Current(InValue.GetBase()), Length(InValue.Num()) { check_code({ MaxLength = InValue.Max(); }); } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator& InValue) { Current = InValue.GetBase(); Length = InValue.Num(); check_code({ MaxLength = InValue.Max(); }); return *this; } + + template requires (CSentinelFor) + NODISCARD friend FORCEINLINE constexpr bool operator==(const TCountedIterator& LHS, const TCountedIterator& RHS) { return LHS.GetBase() == RHS.GetBase(); } + + template requires (CSizedSentinelFor) + NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TCountedIterator& LHS, const TCountedIterator& RHS) { return LHS.GetBase() <=> RHS.GetBase(); } + + 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 decltype(auto) operator*() const { CheckThis(true); return *Current; } + NODISCARD FORCEINLINE constexpr decltype(auto) operator->() const { CheckThis(true); return AddressOf(operator*()); } + + NODISCARD FORCEINLINE constexpr decltype(auto) 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 decltype(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 friend FORCEINLINE constexpr TCountedIterator operator+(TCountedIterator Iter, ptrdiff Offset) requires (CRandomAccessIterator) { TCountedIterator Temp = Iter; Temp += Offset; return Temp; } + NODISCARD friend FORCEINLINE constexpr TCountedIterator operator+(ptrdiff Offset, TCountedIterator Iter) requires (CRandomAccessIterator) { TCountedIterator Temp = Iter; 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 ptrdiff operator-(const TCountedIterator& LHS, const TCountedIterator& RHS) { LHS.CheckThis(); RHS.CheckThis(); return LHS.GetBase() - RHS.GetBase(); } + + 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 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; } + +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(CContiguousIterator>); +static_assert(CSizedSentinelFor>); + NAMESPACE_BEGIN(Iteration) /** Increments given iterator 'Iter' by 'N' elements. */ @@ -415,16 +519,16 @@ FORCEINLINE constexpr decltype(auto) RBegin(T&& Container) } /** Overloads the RBegin algorithm for arrays. */ -template FORCEINLINE constexpr decltype(auto) RBegin( T(& Container)[N]) { return MakeReverseIterator(End(Container)); } -template FORCEINLINE constexpr decltype(auto) RBegin( T(&& Container)[N]) { return MakeReverseIterator(End(Container)); } -template FORCEINLINE constexpr decltype(auto) RBegin(const T(& Container)[N]) { return MakeReverseIterator(End(Container)); } -template FORCEINLINE constexpr decltype(auto) RBegin(const T(&& Container)[N]) { return MakeReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin( T(& Container)[N]) { return TReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin( T(&& Container)[N]) { return TReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin(const T(& Container)[N]) { return TReverseIterator(End(Container)); } +template FORCEINLINE constexpr decltype(auto) RBegin(const T(&& Container)[N]) { return TReverseIterator(End(Container)); } /** Overloads the RBegin algorithm for T::rbegin(). */ template FORCEINLINE constexpr decltype(auto) RBegin(initializer_list Container) { - return MakeReverseIterator(Container.end()); + return TReverseIterator(Container.end()); } /** @return The reverse iterator to the end of a container. */ @@ -435,16 +539,16 @@ FORCEINLINE constexpr decltype(auto) REnd(T&& Container) } /** Overloads the REnd algorithm for arrays. */ -template FORCEINLINE constexpr decltype(auto) REnd( T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); } -template FORCEINLINE constexpr decltype(auto) REnd( T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); } -template FORCEINLINE constexpr decltype(auto) REnd(const T(& Container)[N]) { return MakeReverseIterator(Begin(Container)); } -template FORCEINLINE constexpr decltype(auto) REnd(const T(&& Container)[N]) { return MakeReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd( T(& Container)[N]) { return TReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd( T(&& Container)[N]) { return TReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd(const T(& Container)[N]) { return TReverseIterator(Begin(Container)); } +template FORCEINLINE constexpr decltype(auto) REnd(const T(&& Container)[N]) { return TReverseIterator(Begin(Container)); } /** Overloads the REnd algorithm for T::end(). */ template FORCEINLINE constexpr decltype(auto) REnd(initializer_list Container) { - return MakeReverseIterator(Container.begin()); + return TReverseIterator(Container.begin()); } NAMESPACE_END(Iteration)