diff --git a/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h b/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h index 5707115..58b44bf 100644 --- a/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h +++ b/Redcraft.Utility/Source/Public/Iterator/ContiguousIterator.h @@ -5,6 +5,7 @@ #include "Iterator/Sentinel.h" #include "Iterator/RandomAccessIterator.h" #include "TypeTraits/TypeTraits.h" +#include "Memory/Address.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) diff --git a/Redcraft.Utility/Source/Public/Iterator/CountedIterator.h b/Redcraft.Utility/Source/Public/Iterator/CountedIterator.h new file mode 100644 index 0000000..7cfbc35 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/CountedIterator.h @@ -0,0 +1,152 @@ +#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 diff --git a/Redcraft.Utility/Source/Public/Iterator/InsertIterator.h b/Redcraft.Utility/Source/Public/Iterator/InsertIterator.h new file mode 100644 index 0000000..ddd651b --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/InsertIterator.h @@ -0,0 +1,150 @@ +#pragma once + +#include "CoreTypes.h" +#include "Iterator/Utility.h" +#include "TypeTraits/TypeTraits.h" +#include "Templates/Noncopyable.h" +#include "Templates/Utility.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +NAMESPACE_PRIVATE_BEGIN + +template class TInsertProxy; +template class TPostIncrementProxy; +template class TInsertIterator; + +template +class TInsertProxy final : private FSingleton +{ +public: + +# if DO_CHECK + FORCEINLINE ~TInsertProxy() { checkf(bIsProduced, TEXT("Exception insert, Ensures that the value is assigned to the inserter.")); } +# endif + + template requires (CInvocable) + FORCEINLINE constexpr void operator=(T&& InValue) const + { + checkf(!bIsProduced, TEXT("Exception insert, Ensure that no multiple values are assigned to the inserter.")); + Invoke(Iter.Storage, Forward(InValue)); + check_code({ bIsProduced = true; }); + } + +private: + + TInsertIterator& Iter; + +# if DO_CHECK + mutable bool bIsProduced; +# endif + + FORCEINLINE constexpr TInsertProxy(TInsertIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } + + template friend class TPostIncrementProxy; + template friend class TInsertIterator; +}; + +static_assert(CAssignableFrom, int>); + +template +class TPostIncrementProxy : private FSingleton +{ +public: + +# if DO_CHECK + FORCEINLINE ~TPostIncrementProxy() { checkf(bIsProduced, TEXT("Exception insert, Ensures that the value is assigned to the inserter.")); } +# endif + + NODISCARD FORCEINLINE constexpr TInsertProxy operator*() const + { + checkf(!bIsProduced, TEXT("Exception insert, Ensure that no multiple values are assigned to the inserter.")); + check_code({ bIsProduced = true; }); + return TInsertProxy(Iter); + } + +private: + + TInsertIterator& Iter; + +# if DO_CHECK + mutable bool bIsProduced; +# endif + + FORCEINLINE constexpr TPostIncrementProxy(TInsertIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } + + template friend class TInsertProxy; + template friend class TInsertIterator; +}; + +static_assert(CIndirectlyWritable, int>); + +template +class TInsertIterator final : private FNoncopyable +{ +public: + + FORCEINLINE constexpr TInsertIterator() requires (CDefaultConstructible) = default; + + FORCEINLINE constexpr explicit TInsertIterator(F InInserter) : Storage(MoveTemp(InInserter)) { check_code({ bIsProduced = false; }); } + + FORCEINLINE constexpr TInsertIterator(TInsertIterator&&) = default; + FORCEINLINE constexpr TInsertIterator& operator=(TInsertIterator&&) = default; + + NODISCARD FORCEINLINE constexpr TInsertProxy operator*() + { + checkf(!bIsProduced, TEXT("Exception insert, Ensure that no multiple values are assigned to the inserter.")); + check_code({ bIsProduced = true; }); + return TInsertProxy(*this); + } + + FORCEINLINE constexpr TInsertIterator& operator++() { check_code({ bIsProduced = false; }); return *this; } + + FORCEINLINE constexpr TPostIncrementProxy operator++(int) + { + checkf(!bIsProduced, TEXT("Exception insert, Ensure that no multiple values are assigned to the inserter.")); + return TPostIncrementProxy(*this); + } + +private: + + F Storage; + +# if DO_CHECK + bool bIsProduced; +# endif + + template friend class TInsertProxy; + template friend class TPostIncrementProxy; +}; + +static_assert(COutputIterator, int>); + +NAMESPACE_PRIVATE_END + +/** Creates an iterator adapter inserted in the front of the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeFrontInserter(C& Container) +{ + return NAMESPACE_PRIVATE::TInsertIterator([&Container](T&& A) { Container.PushFront(Forward(A)); }); +} + +/** Creates an iterator adapter inserted in the back of the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container) +{ + return NAMESPACE_PRIVATE::TInsertIterator([&Container](T&& A) { Container.PushBack(Forward(A)); }); +} + +/** Creates an iterator adapter inserted in the container. */ +template +NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& InIter) +{ + return NAMESPACE_PRIVATE::TInsertIterator([&Container, Iter = InIter](T&& A) mutable { Iter = Container.Insert(Iter, Forward(A)); }); +} + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/Iterator.h b/Redcraft.Utility/Source/Public/Iterator/Iterator.h index 8e21b7f..2aa426d 100644 --- a/Redcraft.Utility/Source/Public/Iterator/Iterator.h +++ b/Redcraft.Utility/Source/Public/Iterator/Iterator.h @@ -7,3 +7,7 @@ #include "Iterator/BidirectionalIterator.h" #include "Iterator/RandomAccessIterator.h" #include "Iterator/ContiguousIterator.h" +#include "Iterator/ReverseIterator.h" +#include "Iterator/MoveIterator.h" +#include "Iterator/CountedIterator.h" +#include "Iterator/InsertIterator.h" diff --git a/Redcraft.Utility/Source/Public/Iterator/MoveIterator.h b/Redcraft.Utility/Source/Public/Iterator/MoveIterator.h new file mode 100644 index 0000000..69d9721 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/MoveIterator.h @@ -0,0 +1,156 @@ +#pragma once + +#include "CoreTypes.h" +#include "Iterator/Utility.h" +#include "Iterator/Sentinel.h" +#include "Iterator/ForwardIterator.h" +#include "Iterator/BidirectionalIterator.h" +#include "Iterator/RandomAccessIterator.h" +#include "Iterator/ContiguousIterator.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 IteratorType = I; + + using ElementType = TIteratorElement; + + FORCEINLINE constexpr TMoveIterator() = 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(IteratorType InValue) : Current(MoveTemp(InValue)) { } + + template requires (!CSameAs && CConstructibleFrom) + FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(const TReverseIterator& InValue) : Current(InValue.GetBase()) { } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.GetBase(); return *this; } + + 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 RHS.GetBase() <=> LHS.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 (CRandomAccessIterator) { return LHS.GetBase() - RHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } + +private: + + IteratorType 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 SentinelType = 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(SentinelType 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 SentinelType& GetBase() const& { return Last; } + NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Last); } + +private: + + SentinelType 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 diff --git a/Redcraft.Utility/Source/Public/Iterator/ReverseIterator.h b/Redcraft.Utility/Source/Public/Iterator/ReverseIterator.h new file mode 100644 index 0000000..061b239 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Iterator/ReverseIterator.h @@ -0,0 +1,102 @@ +#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/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 for reverse-order traversal. + * When based on at least a bidirectional iterator, the reverse iterator satisfies at least a bidirectional iterator + * up to a random access iterator. When based on an output iterator, the reverse iterator satisfies an output iterator. + */ +template +class TReverseIterator final +{ +public: + + using IteratorType = I; + + using ElementType = TIteratorElement; + + FORCEINLINE constexpr TReverseIterator() = default; + FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default; + FORCEINLINE constexpr TReverseIterator(TReverseIterator&&) = default; + FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator&) = default; + FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default; + FORCEINLINE constexpr ~TReverseIterator() = default; + + FORCEINLINE constexpr explicit TReverseIterator(IteratorType InValue) : Current(InValue) { } + + template requires (!CSameAs && CConstructibleFrom) + FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(const TReverseIterator& InValue) : Current(InValue.GetBase()) { } + + template requires (!CSameAs && CConvertibleTo && CAssignableFrom) + FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.GetBase(); return *this; } + + 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(); } + + NODISCARD FORCEINLINE constexpr TIteratorReference operator*() const { IteratorType Temp = GetBase(); return *--Temp; } + + NODISCARD FORCEINLINE constexpr auto operator->() const requires (requires(const I Iter) { { ToAddress(Iter) } -> CSameAs>; }) { IteratorType Temp = GetBase(); return ToAddress(--Temp); } + + NODISCARD FORCEINLINE constexpr TIteratorReference operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return GetBase()[-Index - 1]; } + + FORCEINLINE constexpr TReverseIterator& operator++() { --Current; return *this; } + FORCEINLINE constexpr TReverseIterator& operator--() { ++Current; return *this; } + + FORCEINLINE constexpr TReverseIterator operator++(int) { TReverseIterator Temp = *this; --Current; return Temp; } + FORCEINLINE constexpr TReverseIterator operator--(int) { TReverseIterator Temp = *this; ++Current; return Temp; } + + FORCEINLINE constexpr TReverseIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; return *this; } + FORCEINLINE constexpr TReverseIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; return *this; } + + NODISCARD FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset) const requires (CRandomAccessIterator) { TReverseIterator Temp = *this; Temp -= Offset; return Temp; } + NODISCARD FORCEINLINE constexpr TReverseIterator operator-(ptrdiff Offset) const requires (CRandomAccessIterator) { TReverseIterator Temp = *this; Temp += Offset; return Temp; } + + NODISCARD friend FORCEINLINE constexpr TReverseIterator operator+(ptrdiff Offset, const TReverseIterator& Iter) requires (CRandomAccessIterator) { return Iter + Offset; } + + NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) requires (CRandomAccessIterator) { return RHS.GetBase() - LHS.GetBase(); } + + NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } + NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } + +private: + + IteratorType Current; + +}; + +template requires (!CSizedSentinelFor) +inline constexpr bool bDisableSizedSentinelFor, TReverseIterator> = true; + +static_assert(CBidirectionalIterator>>); +static_assert( CRandomAccessIterator>>); +static_assert( CRandomAccessIterator>>); + +static_assert(COutputIterator>, int>); + +/** Creates a TReverseIterator of type inferred from the argument. */ +template requires (CBidirectionalIterator> && CConstructibleFrom, I>) +NODISCARD FORCEINLINE constexpr auto MakeReverseIterator(I&& Iter) +{ + return TReverseIterator>(Forward(Iter)); +} + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Iterator/Sentinel.h b/Redcraft.Utility/Source/Public/Iterator/Sentinel.h index 99eead8..a633ff1 100644 --- a/Redcraft.Utility/Source/Public/Iterator/Sentinel.h +++ b/Redcraft.Utility/Source/Public/Iterator/Sentinel.h @@ -92,6 +92,20 @@ static_assert( } ); +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{ }; + #if PLATFORM_COMPILER_GCC # pragma GCC diagnostic pop #endif diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h b/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h index 4f72399..6245297 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/Iterator.h @@ -1,13 +1,8 @@ #pragma once #include "CoreTypes.h" -#include "Memory/Address.h" -#include "Templates/Invoke.h" #include "Iterator/Iterator.h" -#include "Templates/Utility.h" -#include "Templates/Noncopyable.h" #include "TypeTraits/TypeTraits.h" -#include "Miscellaneous/Compare.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN @@ -116,491 +111,6 @@ concept CIndirectlySwappable = CIndirectlyReadable && CIndirectlyReadable IndirectlySwap(Jter, Iter); }; -/** A iterator adaptor for reverse-order traversal. */ -template -class TReverseIterator final -{ -public: - - using IteratorType = I; - - using ElementType = TIteratorElementType; - - FORCEINLINE constexpr TReverseIterator() = default; - - FORCEINLINE constexpr TReverseIterator(const TReverseIterator&) = default; - FORCEINLINE constexpr TReverseIterator(TReverseIterator&&) = default; - FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator&) = default; - FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&&) = default; - - FORCEINLINE constexpr ~TReverseIterator() = default; - - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TReverseIterator(T&& InValue) : Current(Forward(InValue)) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(const TReverseIterator& InValue) : Current(InValue.Current) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(TReverseIterator&& InValue) : Current(MoveTemp(InValue).Current) { } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.Current; return *this; } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&& InValue) { Current = MoveTemp(InValue).Current; return *this; } - - template requires (CSentinelFor) - NODISCARD friend FORCEINLINE constexpr bool operator==(const TReverseIterator& LHS, const TReverseIterator& RHS) { return LHS.Current == RHS.Current; } - - template requires (CSizedSentinelFor) - NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.Current <=> LHS.Current; } - - NODISCARD FORCEINLINE constexpr TIteratorReferenceType operator*() const { IteratorType Temp = Current; return *--Temp; } - NODISCARD FORCEINLINE constexpr TIteratorPointerType operator->() const { IteratorType Temp = Current; return ToAddress(--Temp); } - - NODISCARD FORCEINLINE constexpr TIteratorReferenceType operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return Current[-Index - 1]; } - - FORCEINLINE constexpr TReverseIterator& operator++() { --Current; return *this; } - FORCEINLINE constexpr TReverseIterator& operator--() { ++Current; return *this; } - - FORCEINLINE constexpr TReverseIterator operator++(int) { TReverseIterator Temp = *this; --Current; return Temp; } - FORCEINLINE constexpr TReverseIterator operator--(int) { TReverseIterator Temp = *this; ++Current; return Temp; } - - FORCEINLINE constexpr TReverseIterator& operator+=(ptrdiff Offset) requires (CRandomAccessIterator) { Current -= Offset; return *this; } - FORCEINLINE constexpr TReverseIterator& operator-=(ptrdiff Offset) requires (CRandomAccessIterator) { Current += Offset; return *this; } - - 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) { TReverseIterator Temp = *this; Temp += Offset; return Temp; } - - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TReverseIterator& LHS, const TReverseIterator& RHS) { return RHS.Current - LHS.Current; } - - NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } - -private: - - IteratorType Current; - -}; - -static_assert(CRandomAccessIterator>); - -template requires (!CSizedSentinelFor) -inline constexpr bool bDisableSizedSentinelFor, TReverseIterator> = true; - -/** An iterator adaptor which dereferences to a rvalue reference. */ -template -class TMoveIterator final -{ -public: - - using IteratorType = I; - - using ElementType = TIteratorElementType; - - FORCEINLINE constexpr TMoveIterator() = 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; - - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TMoveIterator(T&& InValue) : Current(Forward(InValue)) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(const TMoveIterator& InValue) : Current(InValue.Current) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(TMoveIterator&& InValue) : Current(MoveTemp(InValue).Current) { } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.Current; return *this; } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&& InValue) { Current = MoveTemp(InValue).Current; return *this; } - - template requires (CSentinelFor) - NODISCARD friend FORCEINLINE constexpr bool operator==(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.Current == RHS.Current; } - - template requires (CSizedSentinelFor) - NODISCARD friend FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& LHS, const TMoveIterator& RHS) { return LHS.Current <=> RHS.Current; } - - NODISCARD FORCEINLINE constexpr TIteratorRValueReferenceType operator*() const { return MoveTemp(*Current); } - NODISCARD FORCEINLINE constexpr TIteratorPointerType operator->() const = delete; - - NODISCARD FORCEINLINE constexpr TIteratorRValueReferenceType operator[](ptrdiff Index) const requires (CRandomAccessIterator) { return MoveTemp(Current[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 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) { TMoveIterator Temp = *this; Temp -= Offset; return Temp; } - - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& LHS, const TMoveIterator& RHS) requires (CSizedSentinelFor) { return LHS.Current - RHS.Current; } - - NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return MoveTemp(Current); } - -private: - - IteratorType Current; - -}; - -static_assert(CRandomAccessIterator>); - -/** A sentinel adaptor for use with TMoveIterator. */ -template -class TMoveSentinel -{ -public: - - using SentinelType = 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; - - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TMoveSentinel(T&& InValue) : Current(Forward(InValue)) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(const TMoveSentinel& InValue) : Current(InValue.Current) { } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(TMoveSentinel&& InValue) : Current(MoveTemp(InValue).Current) { } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel& InValue) { Current = InValue.Current; return *this; } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&& InValue) { Current = MoveTemp(InValue).Current; return *this; } - - template requires (CSentinelFor) - NODISCARD FORCEINLINE constexpr bool operator==(const TMoveIterator& InValue) const& { return Current == InValue.Current; } - - template requires (CSizedSentinelFor) - NODISCARD FORCEINLINE constexpr TCompareThreeWayResult operator<=>(const TMoveIterator& InValue) const& { return Current <=> InValue.Current; } - - template requires (CSizedSentinelFor) - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveSentinel& Sentinel, const TMoveIterator& Iter) { return Sentinel.Current - Iter.Current; } - - template requires (CSizedSentinelFor) - NODISCARD friend FORCEINLINE constexpr ptrdiff operator-(const TMoveIterator& Iter, const TMoveSentinel& Sentinel) { return Iter.Current - Sentinel.Current; } - - NODISCARD FORCEINLINE constexpr const SentinelType& GetBase() const& { return Current; } - NODISCARD FORCEINLINE constexpr SentinelType GetBase() && { return MoveTemp(Current); } - -private: - - SentinelType Current; - -}; - -static_assert(CSizedSentinelFor, TMoveIterator>); - -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 ~TCountedIterator() = default; - - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TCountedIterator(T&& 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.Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } - - template requires (!CSameAs && CConstructibleFrom) - FORCEINLINE constexpr explicit (!CConvertibleTo) TCountedIterator(TCountedIterator&& InValue) : Current(MoveTemp(InValue).Current), Length(InValue.Num()) { check_code({ MaxLength = InValue.MaxLength; }); } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TCountedIterator& operator=(const TCountedIterator& InValue) { Current = InValue.Current; Length = InValue.Num(); check_code({ MaxLength = InValue.MaxLength; }); return *this; } - - template requires (!CSameAs && CConvertibleTo && CAssignableFrom) - FORCEINLINE constexpr TCountedIterator& operator=(TCountedIterator&& InValue) { Current = MoveTemp(InValue).Current; 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 TIteratorReferenceType operator*() { CheckThis(true); return *Current; } - - NODISCARD FORCEINLINE constexpr TIteratorReferenceType operator*() const requires (CDereferenceable) { CheckThis(true); return *Current; } - - NODISCARD FORCEINLINE constexpr TIteratorPointerType operator->() const requires (CContiguousIterator) { CheckThis(false); return ToAddress(Current); } - - NODISCARD FORCEINLINE constexpr TIteratorReferenceType 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 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; } - - 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) { 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(CContiguousIterator>); -static_assert(CSizedSentinelFor>); - -NAMESPACE_PRIVATE_BEGIN - -/** An output iterator adapter that wraps a callable object. */ -template -class TOutputIterator final : private FNoncopyable -{ -public: - - using Outputer = F; - -private: - - class FIndirectionProxy : private FSingleton - { - public: - - FORCEINLINE constexpr FIndirectionProxy(TOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } - -# if DO_CHECK - FORCEINLINE ~FIndirectionProxy() - { - checkf(bIsProduced, TEXT("Exception output, Ensures that the value is assigned to the output iterator.")); - } -# endif - - template requires (CInvocable) - FORCEINLINE constexpr void operator=(T&& InValue) const - { - checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); - Invoke(Iter.Storage, Forward(InValue)); - check_code({ bIsProduced = true; }); - } - - private: - - TOutputIterator& Iter; - -# if DO_CHECK - mutable bool bIsProduced; -# endif - - }; - - class FPostIncrementProxy : private FSingleton - { - public: - - FORCEINLINE constexpr FPostIncrementProxy(TOutputIterator& InIter) : Iter(InIter) { check_code({ bIsProduced = false; }); } - -# if DO_CHECK - FORCEINLINE ~FPostIncrementProxy() - { - checkf(bIsProduced, TEXT("Exception output, Ensures that the value is assigned to the output iterator.")); - } -# endif - - NODISCARD FORCEINLINE constexpr FIndirectionProxy operator*() const - { - checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); - check_code({ bIsProduced = true; }); - return FIndirectionProxy(Iter); - } - - private: - - TOutputIterator& Iter; - -# if DO_CHECK - mutable bool bIsProduced; -# endif - - }; - -public: - - FORCEINLINE constexpr TOutputIterator() requires (CDefaultConstructible) { check_code({ bIsProduced = false; }); } - - template requires (!CSameAs> && CConstructibleFrom) - FORCEINLINE constexpr explicit TOutputIterator(T&& InOutputer) : Storage(Forward(InOutputer)) { check_code({ bIsProduced = false; }); } - - NODISCARD FORCEINLINE constexpr FIndirectionProxy operator*() - { - checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); - check_code({ bIsProduced = true; }); - return FIndirectionProxy(*this); - } - - FORCEINLINE constexpr TOutputIterator& operator++() { check_code({ bIsProduced = false; }); return *this; } - - FORCEINLINE constexpr FPostIncrementProxy operator++(int) - { - checkf(!bIsProduced, TEXT("Exception output, Ensure that no multiple values are assigned to the output iterator.")); - return FPostIncrementProxy(*this); - } - - NODISCARD FORCEINLINE constexpr const Outputer& GetOutputer() const& { return Storage; } - NODISCARD FORCEINLINE constexpr Outputer GetOutputer() && { return Storage; } - -private: - - Outputer Storage; - -# if DO_CHECK - bool bIsProduced; -# endif - -}; - -static_assert(COutputIterator, int32>); - -template -TOutputIterator(F) -> TOutputIterator; - -NAMESPACE_PRIVATE_END - -/** Creates a TReverseIterator of type inferred from the argument. */ -template requires (CBidirectionalIterator> && CConstructibleFrom, I>) -NODISCARD FORCEINLINE constexpr auto MakeReverseIterator(I&& Iter) -{ - return TReverseIterator>(Forward(Iter)); -} - -/** 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)); -} - -/** 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); -} - -/** Creates an iterator adapter inserted in the front of the container. */ -template -NODISCARD FORCEINLINE constexpr auto MakeFrontInserter(C& Container) -{ - return NAMESPACE_PRIVATE::TOutputIterator([&Container](T&& A) { Container.PushFront(Forward(A)); }); -} - -/** Creates an iterator adapter inserted in the back of the container. */ -template -NODISCARD FORCEINLINE constexpr auto MakeBackInserter(C& Container) -{ - return NAMESPACE_PRIVATE::TOutputIterator([&Container](T&& A) { Container.PushBack(Forward(A)); }); -} - -/** Creates an iterator adapter inserted in the container. */ -template -NODISCARD FORCEINLINE constexpr auto MakeInserter(C& Container, const typename C::ConstIterator& InIter) -{ - return NAMESPACE_PRIVATE::TOutputIterator([&Container, Iter = InIter](T&& A) mutable { Iter = Container.Insert(Iter, Forward(A)); }); -} - NAMESPACE_BEGIN(Iteration) /** @return The iterator to the beginning of a container. */ @@ -685,12 +195,6 @@ FORCEINLINE constexpr auto REnd(initializer_list Container) NAMESPACE_END(Iteration) -#define ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT public: \ - NODISCARD FORCEINLINE constexpr auto begin() { return Begin(); } \ - NODISCARD FORCEINLINE constexpr auto begin() const { return Begin(); } \ - NODISCARD FORCEINLINE constexpr auto end() { return End(); } \ - NODISCARD FORCEINLINE constexpr auto end() const { return End(); } - NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END