#pragma once #include "CoreTypes.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "Templates/Optional.h" #include "Templates/Noncopyable.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Compare.h" #include "Memory/ObserverPointer.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_PRIVATE_BEGIN template using WithReference = T&; template struct TIteratorElementType { using Type = typename I::ElementType; }; template struct TIteratorElementType { using Type = T; }; NAMESPACE_PRIVATE_END template concept CReferenceable = requires { typename NAMESPACE_PRIVATE::WithReference; }; template concept CDereferenceable = requires(T& A) { { *A } -> CReferenceable; }; template using TIteratorElementType = typename NAMESPACE_PRIVATE::TIteratorElementType>::Type; template using TIteratorReferenceType = decltype(*DeclVal()); template requires (requires(I& Iter) { { MoveTemp(*Iter) } -> CReferenceable; }) using TIteratorRValueReferenceType = decltype(MoveTemp(*DeclVal())); template concept CIndirectlyReadable = requires(const TRemoveCVRef Iter) { typename TIteratorElementType; typename TIteratorReferenceType; typename TIteratorRValueReferenceType; { *Iter } -> CSameAs>; { MoveTemp(*Iter) } -> CSameAs>; } && CCommonReference&&, TIteratorElementType&> && CCommonReference&&, TIteratorRValueReferenceType&&> && CCommonReference&&, const TIteratorElementType&>; template concept CIndirectlyWritable = requires(I&& Iter, T&& A) { *Iter = Forward(A); *Forward(Iter) = Forward(A); const_cast&&>(*Iter) = Forward(A); const_cast&&>(*Forward(Iter)) = Forward(A); }; template concept CWeaklyIncrementable = CMovable && requires(I Iter) { { ++Iter } -> CSameAs; Iter++; }; template concept CIncrementable = CRegular && CWeaklyIncrementable && requires(I Iter) { { Iter++ } -> CSameAs; }; template concept CInputOrOutputIterator = CWeaklyIncrementable && requires(I Iter) { { *Iter } -> CReferenceable; }; template concept CSentinelFor = CSemiregular && CInputOrOutputIterator && CWeaklyEqualityComparable; template inline constexpr bool bDisableSizedSentinelFor = false; template concept CSizedSentinelFor = CSentinelFor && CPartiallyOrdered && !bDisableSizedSentinelFor, TRemoveCV> && requires(const I& Iter, const S& Sentinel) { Sentinel - Iter; Iter - Sentinel; }; template concept CInputIterator = CInputOrOutputIterator && CIndirectlyReadable; template concept COutputIterator = CInputOrOutputIterator && CIndirectlyWritable && requires(I Iter, T&& A) { *Iter++ = Forward(A); }; template concept CForwardIterator = CInputIterator && CIncrementable && CSentinelFor; template concept CBidirectionalIterator = CForwardIterator && requires(I Iter) { { --Iter } -> CSameAs; { Iter-- } -> CSameAs; }; template concept CRandomAccessIterator = CBidirectionalIterator && CTotallyOrdered && CSizedSentinelFor && requires(I Iter, const I Jter, const ptrdiff N) { { Iter += N } -> CSameAs; { Jter + N } -> CSameAs; { N + Jter } -> CSameAs; { Iter -= N } -> CSameAs; { Jter - N } -> CSameAs; { Jter[N] } -> CSameAs>; }; template concept CContiguousIterator = CRandomAccessIterator && CLValueReference> && CSameAs, TRemoveReference>> && requires(I& Iter) { static_cast[]>>(Iter); { AddressOf(*Iter) } -> CSameAs>>; }; static_assert(CContiguousIterator); /** 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; 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.GetBase()) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TReverseIterator(TReverseIterator&& InValue) : Current(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TReverseIterator& operator=(const TReverseIterator& InValue) { Current = InValue.GetBase(); return *this; } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TReverseIterator& operator=(TReverseIterator&& InValue) { Current = MoveTemp(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 (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*()); } NODISCARD FORCEINLINE constexpr ElementType& 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 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.GetBase() - LHS.GetBase(); } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return Current; } private: IteratorType Current; }; static_assert(CRandomAccessIterator>); template TReverseIterator(I) -> TReverseIterator; template requires (!CSizedSentinelFor) inline constexpr bool bDisableSizedSentinelFor, TReverseIterator> = true; /** An iterator adaptor which dereferences to an 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; 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.GetBase()) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveIterator(TMoveIterator&& InValue) : Current(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveIterator& operator=(const TMoveIterator& InValue) { Current = InValue.GetBase(); return *this; } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveIterator& operator=(TMoveIterator&& InValue) { Current = MoveTemp(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 (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]); } 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) { return LHS.GetBase() - RHS.GetBase(); } NODISCARD FORCEINLINE constexpr const IteratorType& GetBase() const& { return Current; } NODISCARD FORCEINLINE constexpr IteratorType GetBase() && { return Current; } private: IteratorType Current; }; static_assert(CRandomAccessIterator>); template TMoveIterator(I) -> TMoveIterator; /** 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; template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TMoveSentinel(T&& InValue) : Last(Forward(InValue)) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(const TMoveSentinel& InValue) : Last(InValue.GetBase()) { } template requires (!CSameAs && CConstructibleFrom) FORCEINLINE constexpr explicit (!CConvertibleTo) TMoveSentinel(TMoveSentinel&& InValue) : Last(MoveTemp(InValue).GetBase()) { } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveSentinel& operator=(const TMoveSentinel& InValue) { Last = InValue.GetBase(); return *this; } template requires (!CSameAs && CConvertibleTo && CAssignableFrom) FORCEINLINE constexpr TMoveSentinel& operator=(TMoveSentinel&& InValue) { Last = MoveTemp(InValue).GetBase(); return *this; } template requires (CSentinelFor) NODISCARD FORCEINLINE constexpr bool operator==(const TMoveIterator& InValue) const& { return GetBase() == InValue.GetBase(); } template requires (CSizedSentinelFor) NODISCARD FORCEINLINE constexpr TCompareThreeWayResult 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 Last; } private: SentinelType Last; }; 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; 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.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 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*() { CheckThis(true); return *Current; } NODISCARD FORCEINLINE constexpr decltype(auto) operator*() const { CheckThis(true); return *Current; } NODISCARD FORCEINLINE constexpr decltype(auto) operator->() { CheckThis(true); return AddressOf(operator*()); } 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 TObserverPtr() const requires (CContiguousIterator) { CheckThis(); return TObserverPtr(Current); } 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(CContiguousIterator>); static_assert(CSizedSentinelFor>); template TCountedIterator(I, ptrdiff) -> TCountedIterator; /** An input iterator adapter that wraps a callable object. */ template requires (CTOptional>> && CMoveConstructible && CConstructibleFrom>, TInvokeResult> && CAssignableFrom>&, TInvokeResult>) class TInputIterator final : private FNoncopyable { public: using Inputer = F; using ElementType = typename TRemoveCVRef>::ValueType; FORCEINLINE constexpr TInputIterator() requires (CDefaultConstructible) : LookAhead(Invoke(Storage)) { }; template requires (!CSameAs> && CConstructibleFrom) FORCEINLINE constexpr explicit TInputIterator(T&& InInputer) : Storage(Forward(InInputer)), LookAhead(Invoke(Storage)) { } NODISCARD FORCEINLINE constexpr bool operator==(FDefaultSentinel) const& { return !LookAhead.IsValid(); } NODISCARD FORCEINLINE constexpr const ElementType& operator*() const { return LookAhead.GetValue(); } FORCEINLINE constexpr TInputIterator& operator++() { LookAhead = Invoke(Storage); return *this; } FORCEINLINE constexpr void operator++(int) { LookAhead = Invoke(Storage); } NODISCARD FORCEINLINE constexpr const Inputer& GetInputer() const& { return Storage; } NODISCARD FORCEINLINE constexpr Inputer GetInputer() && { return Storage; } private: Inputer Storage; TOptional LookAhead; }; static_assert(CInputIterator(*)()>>); template TInputIterator(F) -> TInputIterator; /** 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; /** Creates a TReverseIterator of type inferred from the argument. */ template requires (CBidirectionalIterator> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr TReverseIterator MakeReverseIterator(I&& Iter) { return TReverseIterator>(Forward(Iter)); } /** Creates a TMoveIterator of type inferred from the argument. */ template requires (CInputIterator> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr TMoveIterator MakeMoveIterator(I&& Iter) { return TMoveIterator>(Forward(Iter)); } /** Creates a TMoveSentinel of type inferred from the argument. */ template requires (CSemiregular> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr TMoveSentinel MakeMoveSentinel(I&& Iter) { return TMoveSentinel>(Forward(Iter)); } /** Creates a TCountedIterator of type inferred from the argument. */ template requires (CInputOrOutputIterator> && CConstructibleFrom, I>) NODISCARD FORCEINLINE constexpr TCountedIterator 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 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 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 TOutputIterator([&Container, Iter = InIter](T&& A) mutable { Iter = Container.Insert(Iter, Forward(A)); }); } NAMESPACE_BEGIN(Iteration) /** Increments given iterator 'Iter' by 'N' elements. */ template FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N) { if constexpr (CRandomAccessIterator) { Iter += N; } else if constexpr (CBidirectionalIterator) { for (; N > 0; --N) ++Iter; for (; N < 0; ++N) --Iter; } else { checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented.")); for (; N > 0; --N) ++Iter; } } /** @return The number of hops from 'First' to 'Last'. */ template S> FORCEINLINE constexpr ptrdiff Distance(I First, S Last) { if constexpr (CSizedSentinelFor) { return Last - First; } else { ptrdiff Result = 0; for (; First != Last; ++First) ++Result; return Result; } } /** @return The 'N'-th successor of iterator 'Iter'. */ template FORCEINLINE constexpr I Next(I Iter, TMakeUnsigned N = 1) { Advance(Iter, N); return Iter; } /** @return The 'N'-th predecessor of iterator 'Iter'. */ template FORCEINLINE constexpr I Prev(I Iter, TMakeUnsigned N = 1) { Advance(Iter, -N); return Iter; } /** @return The iterator to the beginning of a container. */ template requires (requires(T&& Container) { { Container.Begin() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) Begin(T&& Container) { return Container.Begin(); } /** Overloads the Begin algorithm for arrays. */ template FORCEINLINE constexpr T* Begin( T(& Container)[N]) { return Container; } template FORCEINLINE constexpr T* Begin( T(&& Container)[N]) { return Container; } template FORCEINLINE constexpr const T* Begin(const T(& Container)[N]) { return Container; } template FORCEINLINE constexpr const T* Begin(const T(&& Container)[N]) { return Container; } /** Overloads the Begin algorithm for initializer_list. */ template FORCEINLINE constexpr decltype(auto) Begin(initializer_list Container) { return Container.begin(); } /** @return The iterator to the end of a container. */ template requires (requires(T&& Container) { { Container.End() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) End(T&& Container) { return Container.End(); } /** Overloads the End algorithm for arrays. */ template FORCEINLINE constexpr T* End( T(& Container)[N]) { return Container + N; } template FORCEINLINE constexpr T* End( T(&& Container)[N]) { return Container + N; } template FORCEINLINE constexpr const T* End(const T(& Container)[N]) { return Container + N; } template FORCEINLINE constexpr const T* End(const T(&& Container)[N]) { return Container + N; } /** Overloads the End algorithm for initializer_list. */ template FORCEINLINE constexpr decltype(auto) End(initializer_list Container) { return Container.end(); } /** @return The reverse iterator to the beginning of a container. */ template requires (requires(T&& Container) { { Container.RBegin() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) RBegin(T&& Container) { return Container.RBegin(); } /** Overloads the RBegin algorithm for arrays. */ 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 initializer_list. */ template FORCEINLINE constexpr decltype(auto) RBegin(initializer_list Container) { return TReverseIterator(Container.end()); } /** @return The reverse iterator to the end of a container. */ template requires (requires(T&& Container) { { Container.REnd() } -> CForwardIterator; }) FORCEINLINE constexpr decltype(auto) REnd(T&& Container) { return Container.REnd(); } /** Overloads the REnd algorithm for arrays. */ 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 initializer_list. */ template FORCEINLINE constexpr decltype(auto) REnd(initializer_list Container) { return TReverseIterator(Container.begin()); } NAMESPACE_END(Iteration) #define ENABLE_RANGE_BASED_FOR_LOOP_SUPPORT public: \ NODISCARD FORCEINLINE constexpr decltype(auto) begin() { return Begin(); } \ NODISCARD FORCEINLINE constexpr decltype(auto) begin() const { return Begin(); } \ NODISCARD FORCEINLINE constexpr decltype(auto) end() { return End(); } \ NODISCARD FORCEINLINE constexpr decltype(auto) end() const { return End(); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END