Compare commits
	
		
			2 Commits
		
	
	
		
			a92422e8b2
			...
			04bb4be901
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 04bb4be901 | |||
| a68a6d16b6 | 
@@ -3,6 +3,7 @@
 | 
				
			|||||||
#include "Algorithms/Algorithms.h"
 | 
					#include "Algorithms/Algorithms.h"
 | 
				
			||||||
#include "Containers/Array.h"
 | 
					#include "Containers/Array.h"
 | 
				
			||||||
#include "Containers/List.h"
 | 
					#include "Containers/List.h"
 | 
				
			||||||
 | 
					#include "Ranges/Factory.h"
 | 
				
			||||||
#include "Miscellaneous/AssertionMacros.h"
 | 
					#include "Miscellaneous/AssertionMacros.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NAMESPACE_REDCRAFT_BEGIN
 | 
					NAMESPACE_REDCRAFT_BEGIN
 | 
				
			||||||
@@ -15,20 +16,109 @@ NAMESPACE_PRIVATE_BEGIN
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void TestBasic()
 | 
					void TestBasic()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TArray<int> Arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 | 
						{
 | 
				
			||||||
 | 
							TArray<int> Arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto Iter = Arr.Begin();
 | 
							auto Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Algorithms::Advance(Iter, 5);
 | 
							Algorithms::Advance(Iter, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	always_check(*Iter == 5);
 | 
							always_check(*Iter == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	always_check(Algorithms::Distance(Arr.Begin(), Iter) == 5);
 | 
							always_check(Algorithms::Distance(Arr.Begin(), Iter) == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	always_check(Algorithms::Distance(Arr) == 10);
 | 
							always_check(Algorithms::Distance(Arr) == 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	always_check(*Algorithms::Next(Iter, 2) == 7);
 | 
							always_check(*Algorithms::Next(Iter)    == 6);
 | 
				
			||||||
	always_check(*Algorithms::Prev(Iter, 2) == 3);
 | 
							always_check(*Algorithms::Next(Iter, 2) == 7);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Prev(Iter)    == 4);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Prev(Iter, 2) == 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter,     Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter, 16, Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Prev(Iter, 16, Arr.Begin()) == Arr.Begin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Advance(Iter, 16, Arr.End()) == 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							TList<int> Arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(*Iter == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Distance(Arr.Begin(), Iter) == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Distance(Arr) == 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(*Algorithms::Next(Iter)    == 6);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Next(Iter, 2) == 7);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Prev(Iter)    == 4);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Prev(Iter, 2) == 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter,     Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter, 16, Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Prev(Iter, 16, Arr.Begin()) == Arr.Begin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Advance(Iter, 16, Arr.End()) == 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto Arr = Ranges::Iota(0, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(*Iter == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Distance(Arr.Begin(), Iter) == 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Distance(Arr) == 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(*Algorithms::Next(Iter)    == 6);
 | 
				
			||||||
 | 
							always_check(*Algorithms::Next(Iter, 2) == 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter,     Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
							always_check(Algorithms::Next(Iter, 16, Arr.End()) == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Iter = Arr.Begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Algorithms::Advance(Iter, 16, Arr.End()) == 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							always_check(Iter == Arr.End());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NAMESPACE_PRIVATE_END
 | 
					NAMESPACE_PRIVATE_END
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
#include "Iterators/Sentinel.h"
 | 
					#include "Iterators/Sentinel.h"
 | 
				
			||||||
#include "Iterators/BasicIterator.h"
 | 
					#include "Iterators/BasicIterator.h"
 | 
				
			||||||
#include "Ranges/Utility.h"
 | 
					#include "Ranges/Utility.h"
 | 
				
			||||||
 | 
					#include "Numerics/Math.h"
 | 
				
			||||||
#include "Miscellaneous/AssertionMacros.h"
 | 
					#include "Miscellaneous/AssertionMacros.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NAMESPACE_REDCRAFT_BEGIN
 | 
					NAMESPACE_REDCRAFT_BEGIN
 | 
				
			||||||
@@ -15,7 +16,7 @@ NAMESPACE_MODULE_BEGIN(Utility)
 | 
				
			|||||||
NAMESPACE_BEGIN(Algorithms)
 | 
					NAMESPACE_BEGIN(Algorithms)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Increments given iterator 'Iter' by 'N' elements. */
 | 
					/** Increments given iterator 'Iter' by 'N' elements. */
 | 
				
			||||||
template <CInputIterator I>
 | 
					template <CInputOrOutputIterator I>
 | 
				
			||||||
FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N)
 | 
					FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if constexpr (CRandomAccessIterator<I>)
 | 
						if constexpr (CRandomAccessIterator<I>)
 | 
				
			||||||
@@ -32,22 +33,84 @@ FORCEINLINE constexpr void Advance(I& Iter, ptrdiff N)
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented."));
 | 
							checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (; N > 0; --N) ++Iter;
 | 
							for (; N > 0; --N) ++Iter;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Increments given iterator 'Iter' to the 'Sent' position. */
 | 
				
			||||||
 | 
					template <CInputOrOutputIterator I, CSentinelFor<I> S>
 | 
				
			||||||
 | 
					FORCEINLINE constexpr void Advance(I& Iter, S Sent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if constexpr (CAssignableFrom<I&, S>)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Iter = Sent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						else if constexpr (CSizedSentinelFor<S, I>)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, Sent - Iter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							for (; Iter != Sent; ++Iter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Increments given iterator 'Iter' by 'N' elements, up to the 'Sent' position. */
 | 
				
			||||||
 | 
					template <CInputOrOutputIterator I, CSentinelFor<I> S>
 | 
				
			||||||
 | 
					FORCEINLINE constexpr ptrdiff Advance(I& Iter, ptrdiff N, S Sent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if constexpr (CSizedSentinelFor<S, I>)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							const ptrdiff Distance = Sent - Iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (Math::Abs(N) > Math::Abs(Distance))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Algorithms::Advance(Iter, Sent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return N - Distance;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Algorithms::Advance(Iter, N);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						else if constexpr (CBidirectionalIterator<I>)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							for (; N > 0 && Iter != Sent; --N) ++Iter;
 | 
				
			||||||
 | 
							for (; N < 0 && Iter != Sent; ++N) --Iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return N;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							checkf(N >= 0, TEXT("The iterator must satisfy the CBidirectionalIterator in order to be decremented."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (; N > 0 && Iter != Sent; --N) ++Iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return N;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @return The number of hops from 'First' to 'Last'. */
 | 
					/** @return The number of hops from 'First' to 'Last'. */
 | 
				
			||||||
template <CInputIterator I, CSentinelFor<I> S>
 | 
					template <CInputOrOutputIterator I, CSentinelFor<I> S>
 | 
				
			||||||
NODISCARD FORCEINLINE constexpr ptrdiff Distance(I First, S Last)
 | 
					NODISCARD FORCEINLINE constexpr ptrdiff Distance(I First, S Last)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if constexpr (CSizedSentinelFor<S, I>)
 | 
						if constexpr (CSizedSentinelFor<S, I>)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return Last - First;
 | 
							return Last - First;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ptrdiff Result = 0;
 | 
							ptrdiff Result = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (; First != Last; ++First) ++Result;
 | 
							for (; First != Last; ++First) ++Result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Result;
 | 
							return Result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -60,25 +123,64 @@ NODISCARD FORCEINLINE constexpr ptrdiff Distance(R&& Range)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		return static_cast<ptrdiff>(Ranges::Num(Range));
 | 
							return static_cast<ptrdiff>(Ranges::Num(Range));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else return Algorithms::Distance(Ranges::Begin(Range), Ranges::End(Range));
 | 
						else return Algorithms::Distance(Ranges::Begin(Range), Ranges::End(Range));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @return The 1-th successor of iterator 'Iter'. */
 | 
				
			||||||
 | 
					template <CInputOrOutputIterator I>
 | 
				
			||||||
 | 
					NODISCARD FORCEINLINE constexpr I Next(I Iter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ++Iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @return The 'N'-th successor of iterator 'Iter'. */
 | 
					/** @return The 'N'-th successor of iterator 'Iter'. */
 | 
				
			||||||
template <CInputIterator I>
 | 
					template <CInputOrOutputIterator I>
 | 
				
			||||||
NODISCARD FORCEINLINE constexpr I Next(I Iter, ptrdiff N = 1)
 | 
					NODISCARD FORCEINLINE constexpr I Next(I Iter, ptrdiff N)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Algorithms::Advance(Iter, N);
 | 
						Algorithms::Advance(Iter, N);
 | 
				
			||||||
	return Iter;
 | 
						return Iter;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @return The successor of iterator 'Iter' to the 'Sent' position. */
 | 
				
			||||||
 | 
					template <CInputOrOutputIterator I, CSentinelFor<I> S>
 | 
				
			||||||
 | 
					NODISCARD FORCEINLINE constexpr I Next(I Iter, S Sent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Algorithms::Advance(Iter, Sent);
 | 
				
			||||||
 | 
						return Iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @return The 'N'-th successor of iterator 'Iter', up to the 'Sent' position. */
 | 
				
			||||||
 | 
					template <CInputOrOutputIterator I, CSentinelFor<I> S>
 | 
				
			||||||
 | 
					NODISCARD FORCEINLINE constexpr I Next(I Iter, ptrdiff N, S Sent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Algorithms::Advance(Iter, N, Sent);
 | 
				
			||||||
 | 
						return Iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @return The 1-th predecessor of iterator 'Iter'. */
 | 
				
			||||||
 | 
					template <CBidirectionalIterator I>
 | 
				
			||||||
 | 
					NODISCARD FORCEINLINE constexpr I Prev(I Iter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return --Iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @return The 'N'-th predecessor of iterator 'Iter'. */
 | 
					/** @return The 'N'-th predecessor of iterator 'Iter'. */
 | 
				
			||||||
template <CBidirectionalIterator I>
 | 
					template <CBidirectionalIterator I>
 | 
				
			||||||
NODISCARD FORCEINLINE constexpr I Prev(I Iter, ptrdiff N = 1)
 | 
					NODISCARD FORCEINLINE constexpr I Prev(I Iter, ptrdiff N)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Algorithms::Advance(Iter, -N);
 | 
						Algorithms::Advance(Iter, -N);
 | 
				
			||||||
	return Iter;
 | 
						return Iter;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @return The predecessor of iterator 'Iter', up to the 'First' position. */
 | 
				
			||||||
 | 
					template <CBidirectionalIterator I>
 | 
				
			||||||
 | 
					NODISCARD FORCEINLINE constexpr I Prev(I Iter, ptrdiff N, I First)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Algorithms::Advance(Iter, -N, First);
 | 
				
			||||||
 | 
						return Iter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NAMESPACE_END(Algorithms)
 | 
					NAMESPACE_END(Algorithms)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NAMESPACE_MODULE_END(Utility)
 | 
					NAMESPACE_MODULE_END(Utility)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user