#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::FConstIterator& 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