From 90048ad3cc4bd8ce777672149a0c69eb9c8115e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Thu, 2 Nov 2017 14:23:19 +0100
Subject: [PATCH] Arrays - C++-style iterators

---
 include/ebcl/Arrays.hh        |  77 ++++
 include/ebcl/Utilities.hh     |  61 +++
 include/ebcl/inline/Arrays.hh | 483 ++++++++++++++++++++
 tests/arrays-iter.cc          | 822 ++++++++++++++++++++++++++++++++++
 tests/list.mk                 |   1 +
 5 files changed, 1444 insertions(+)
 create mode 100644 tests/arrays-iter.cc

diff --git a/include/ebcl/Arrays.hh b/include/ebcl/Arrays.hh
index 1d381f9..0c5c524 100644
--- a/include/ebcl/Arrays.hh
+++ b/include/ebcl/Arrays.hh
@@ -22,6 +22,62 @@ class T_Array final
 		return std::max< uint32_t >( 1 , 4096 / sizeof( T ) );
 	}
 
+	template< ptrdiff_t Direction >
+	class T_Iterator_ final : public std::iterator<
+				std::random_access_iterator_tag , T >
+	{
+	    private:
+		T_Array< T >* array_;
+		ptrdiff_t pos_;
+
+	    public:
+		T_Iterator_( T_Array< T >& array ,
+				const ptrdiff_t pos ) noexcept;
+
+		M_ITER_CONS_DEF( T_Iterator_ );
+		M_ITER_CONS_COPY( T_Iterator_ );
+		M_ITER_SWAP( T_Iterator_ , T_Array );
+		M_ITER_CMP_ALL( T_Iterator_ );
+		M_ITER_DEREF_RANDOM( T& , T* );
+		M_ITER_OPS_RANDOM( T_Iterator_ );
+
+		bool valid( ) const noexcept;
+		T_Array< T >* target( ) const noexcept;
+		ptrdiff_t pos( ) const noexcept;
+	};
+	using T_Iterator = T_Iterator_< 1 >;
+	using T_ReverseIterator = T_Iterator_< -1 >;
+
+	template< ptrdiff_t Direction >
+	class T_ConstIterator_ : public std::iterator<
+				std::random_access_iterator_tag , T >
+	{
+	    private:
+		T_Array< T > const* array_;
+		ptrdiff_t pos_;
+
+	    public:
+		T_ConstIterator_( T_Array< T > const& array ,
+				const ptrdiff_t pos ) noexcept;
+
+		T_ConstIterator_( typename T_Array< T >::T_Iterator const& iterator ) noexcept;
+		T_ConstIterator_& operator =(
+				typename T_Array< T >::T_Iterator const& iterator ) noexcept;
+
+		M_ITER_CONS_DEF( T_ConstIterator_ );
+		M_ITER_CONS_COPY( T_ConstIterator_ );
+		M_ITER_SWAP( T_ConstIterator_ , T_Array );
+		M_ITER_CMP_ALL( T_ConstIterator_ );
+		M_ITER_DEREF_RANDOM( T const& , T const* );
+		M_ITER_OPS_RANDOM( T_ConstIterator_ );
+
+		bool valid( ) const noexcept;
+		T_Array< T >* target( ) const noexcept;
+		ptrdiff_t pos( ) const noexcept;
+	};
+	using T_ConstIterator = T_ConstIterator_< 1 >;
+	using T_ConstReverseIterator = T_ConstIterator_< -1 >;
+
    private:
 	typedef T_Array< T > MyType_;
 
@@ -121,6 +177,27 @@ class T_Array final
 
 	MyType_ moveRange( uint32_t first ,
 			uint32_t last = UINT32_MAX ) noexcept;
+
+	// ---------------------------------------------------------------------
+	// Iterators for C++ for loops
+
+	T_ConstIterator begin( ) const noexcept;
+	T_ConstIterator end( ) const noexcept;
+
+	T_ConstReverseIterator rbegin( ) const noexcept;
+	T_ConstReverseIterator rend( ) const noexcept;
+
+	T_ConstIterator cbegin( ) const noexcept;
+	T_ConstIterator cend( ) const noexcept;
+
+	T_ConstReverseIterator crbegin( ) const noexcept;
+	T_ConstReverseIterator crend( ) const noexcept;
+
+	T_Iterator begin( ) noexcept;
+	T_Iterator end( ) noexcept;
+
+	T_ReverseIterator rbegin( ) noexcept;
+	T_ReverseIterator rend( ) noexcept;
 };
 
 // Instantiate some common types directly
diff --git a/include/ebcl/Utilities.hh b/include/ebcl/Utilities.hh
index 54c497a..7234056 100644
--- a/include/ebcl/Utilities.hh
+++ b/include/ebcl/Utilities.hh
@@ -234,6 +234,67 @@ template< typename T >
 #define M_DEFINE_SWAP( Type ) \
 	void swap( Type& lhs , Type& rhs ) noexcept
 
+/*----------------------------------------------------------------------------*/
+/* Helper macros for iterator declarations */
+
+// Default constructor (forward, bidir, random)
+#define M_ITER_CONS_DEF( NAME )						\
+	NAME( ) noexcept
+
+// Copy constructor/assignment (all types)
+#define M_ITER_CONS_COPY( NAME )					\
+	NAME( NAME const& other ) noexcept;				\
+	NAME& operator =( NAME const& other ) noexcept
+
+// Move constructor (not necessary)
+#define M_ITER_CONS_MOVE( NAME )					\
+	NAME( NAME&& other ) noexcept;					\
+	NAME& operator =( NAME&& other ) noexcept
+
+// Swap (all types)
+#define M_ITER_SWAP( NAME , CONTAINER )					\
+	template< typename SwapType_ >					\
+	friend void swap( typename CONTAINER< SwapType_ >::NAME& lhs ,	\
+			typename CONTAINER< SwapType_ >::NAME& rhs	\
+		) noexcept
+
+// Equality/inequality (all types)
+#define M_ITER_CMP_EQ( NAME )						\
+	bool operator ==( NAME const& other ) const noexcept;		\
+	bool operator !=( NAME const& other ) const noexcept
+
+// Equality/inequality (all types)
+#define M_ITER_CMP_ALL( NAME )						\
+	M_ITER_CMP_EQ( NAME );						\
+	bool operator >( NAME const& other ) const noexcept;		\
+	bool operator >=( NAME const& other ) const noexcept;		\
+	bool operator <( NAME const& other ) const noexcept;		\
+	bool operator <=( NAME const& other ) const noexcept
+
+// Dereference
+#define M_ITER_DEREF( REF , PTR )					\
+	REF operator* ( ) const noexcept;				\
+	PTR operator-> ( ) const noexcept
+#define M_ITER_DEREF_RANDOM( REF , PTR )				\
+	M_ITER_DEREF( REF , PTR );					\
+	REF operator[] ( const ptrdiff_t offset ) const noexcept
+
+// Operations (increment, etc)
+#define M_ITER_OPS_FWD( NAME )						\
+	NAME& operator++ ( ) noexcept;					\
+	NAME operator++ (int) noexcept
+#define M_ITER_OPS_BIDIR( NAME )					\
+	M_ITER_OPS_FWD( NAME );						\
+	NAME& operator-- ( ) noexcept;					\
+	NAME operator-- (int) noexcept
+#define M_ITER_OPS_RANDOM( NAME )					\
+	M_ITER_OPS_BIDIR( NAME );					\
+	NAME operator +( const ptrdiff_t value ) const noexcept;	\
+	NAME operator -( const ptrdiff_t value ) const noexcept;	\
+	ptrdiff_t operator -( NAME const& other ) const noexcept;		\
+	NAME& operator +=( const ptrdiff_t value ) noexcept;		\
+	NAME& operator -=( const ptrdiff_t value ) noexcept
+
 
 /*= ENDIAN DETECTION =========================================================*/
 /*
diff --git a/include/ebcl/inline/Arrays.hh b/include/ebcl/inline/Arrays.hh
index 11a57b4..ea1bb86 100644
--- a/include/ebcl/inline/Arrays.hh
+++ b/include/ebcl/inline/Arrays.hh
@@ -463,6 +463,489 @@ inline T_Array< T > T_Array< T >::moveRange(
 	return output;
 }
 
+/*----------------------------------------------------------------------------*/
+
+#define M_ITER_( NAME ) typename T_Array< T >::T_ ##NAME
+
+template< typename T >
+inline M_ITER_( ConstIterator ) T_Array< T >::begin( ) const noexcept
+{
+	return T_ConstIterator( *this , 0 );
+}
+
+template< typename T >
+inline M_ITER_( ConstIterator ) T_Array< T >::end( ) const noexcept
+{
+	return T_ConstIterator( *this , size_ );
+}
+
+template< typename T >
+inline M_ITER_( Iterator ) T_Array< T >::begin( ) noexcept
+{
+	return T_Iterator( *this , 0 );
+}
+
+template< typename T >
+inline M_ITER_( Iterator ) T_Array< T >::end( ) noexcept
+{
+	return T_Iterator( *this , size_ );
+}
+
+template< typename T >
+inline M_ITER_( ConstReverseIterator ) T_Array< T >::rbegin( ) const noexcept
+{
+	return T_ConstReverseIterator( *this , 0 );
+}
+
+template< typename T >
+inline M_ITER_( ConstReverseIterator ) T_Array< T >::rend( ) const noexcept
+{
+	return T_ConstReverseIterator( *this , size_ );
+}
+
+template< typename T >
+inline M_ITER_( ReverseIterator ) T_Array< T >::rbegin( ) noexcept
+{
+	return T_ReverseIterator( *this , size_ - 1 );
+}
+
+template< typename T >
+inline M_ITER_( ReverseIterator ) T_Array< T >::rend( ) noexcept
+{
+	return T_ReverseIterator( *this , -1 );
+}
+
+template< typename T >
+inline M_ITER_( ConstIterator ) T_Array< T >::cbegin( ) const noexcept
+{
+	return T_ConstIterator( *this , 0 );
+}
+
+template< typename T >
+inline M_ITER_( ConstIterator ) T_Array< T >::cend( ) const noexcept
+{
+	return T_ConstIterator( *this , size_ );
+}
+
+template< typename T >
+inline M_ITER_( ConstReverseIterator ) T_Array< T >::crbegin( ) const noexcept
+{
+	return T_ConstReverseIterator( *this , 0 );
+}
+
+template< typename T >
+inline M_ITER_( ConstReverseIterator ) T_Array< T >::crend( ) const noexcept
+{
+	return T_ConstReverseIterator( *this , size_ );
+}
+
+#undef M_ITER_
+
+
+/*= T_Array::T_Iterator_ =====================================================*/
+
+#define M_HDR_ template< typename T > template< ptrdiff_t D >
+#define M_CNAME_ T_Array< T >::T_Iterator_< D >
+#define M_CNAME_T_ typename T_Array< T >::template T_Iterator_< D >
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_::T_Iterator_(
+		T_Array< T >& array ,
+		const ptrdiff_t pos ) noexcept
+	: array_( &array ) , pos_( pos )
+{ }
+
+M_HDR_ inline M_CNAME_::T_Iterator_( ) noexcept
+	: array_( nullptr ) , pos_( 0 )
+{ }
+
+M_HDR_ inline M_CNAME_::T_Iterator_(
+		T_Iterator_ const& other ) noexcept
+	: array_( other.array_ ) , pos_( other.pos_ )
+{ }
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator=(
+		T_Iterator_ const& other ) noexcept
+{
+	array_ = other.array_;
+	pos_ = other.pos_;
+	return *this;
+}
+
+/*----------------------------------------------------------------------------*/
+
+template< typename T , ptrdiff_t D>
+inline void swap(
+		M_CNAME_T_& lhs ,
+		M_CNAME_T_& rhs ) noexcept
+{
+	std::swap( lhs.array_ , rhs.array_ );
+	std::swap( lhs.pos_ , rhs.pos_ );
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::operator==(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ == other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator!=(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ != other.array_ || pos_ != other.pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::operator <(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ < other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator<=(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ <= other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator >(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ > other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator>=(
+		T_Iterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ >= other.pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline T& M_CNAME_::operator*( ) const noexcept
+{
+	assert( valid( ) );
+	return (*array_)[ pos_ ];
+}
+
+M_HDR_ inline T* M_CNAME_::operator->( ) const noexcept
+{
+	assert( valid( ) );
+	return &((*array_)[ pos_ ]);
+}
+
+M_HDR_ inline T& M_CNAME_::operator[](
+		const ptrdiff_t pos ) const noexcept
+{
+	const auto idx( pos + pos_ );
+	assert( array_ && idx >= 0 && idx < array_->size( ) );
+	return (*array_)[ idx ];
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator++ () noexcept
+{
+	assert( valid( ) );
+	pos_ += D;
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept
+{
+	assert( valid( ) );
+	auto copy( *this );
+	pos_ += D;
+	return copy;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept
+{
+	assert( valid( ) );
+	pos_ -= D;
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept
+{
+	assert( valid( ) );
+	auto copy( *this );
+	pos_ -= D;
+	return copy;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator +(
+		const ptrdiff_t value ) const noexcept
+{
+	auto copy( *this );
+	copy += value;
+	return copy;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator -(
+		const ptrdiff_t value ) const noexcept
+{
+	auto copy( *this );
+	copy -= value;
+	return copy;
+}
+
+M_HDR_ inline ptrdiff_t M_CNAME_::operator -(
+		M_CNAME_T_ const& other ) const noexcept
+{
+	assert( array_ && array_ == other.array_ );
+	return pos_ - other.pos_;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator +=(
+		const ptrdiff_t value ) noexcept
+{
+	assert( valid( ) );
+	pos_ = std::min( ptrdiff_t( array_->size( ) ) ,
+		std::max( ptrdiff_t( -1 ) , pos_ + value * D ) );
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator -=(
+		const ptrdiff_t value ) noexcept
+{
+	assert( valid( ) );
+	pos_ = std::min( ptrdiff_t( array_->size( ) ) ,
+		std::max( ptrdiff_t( -1 ) , pos_ - value * D ) );
+	return *this;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::valid( ) const noexcept
+{
+	return array_ && pos_ >= 0 && pos_ < array_->size( );
+}
+
+M_HDR_ inline T_Array< T >* M_CNAME_::target( ) const noexcept
+{
+	return array_;
+}
+
+M_HDR_ inline ptrdiff_t M_CNAME_::pos( ) const noexcept
+{
+	return pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+#undef M_HDR_
+#undef M_CNAME_
+#undef M_CNAME_T_
+
+
+/*= T_Array::T_ConstIterator_ ================================================*/
+
+#define M_HDR_ template< typename T > template< ptrdiff_t D >
+#define M_CNAME_ T_Array< T >::T_ConstIterator_< D >
+#define M_CNAME_T_ typename T_Array< T >::template T_ConstIterator_< D >
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_::T_ConstIterator_(
+		T_Array< T > const& array ,
+		const ptrdiff_t pos ) noexcept
+	: array_( &array ) , pos_( pos )
+{ }
+
+M_HDR_ inline M_CNAME_::T_ConstIterator_( ) noexcept
+	: array_( nullptr ) , pos_( 0 )
+{ }
+
+M_HDR_ inline M_CNAME_::T_ConstIterator_(
+		T_ConstIterator_ const& other ) noexcept
+	: array_( other.array_ ) , pos_( other.pos_ )
+{ }
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator=(
+		T_ConstIterator_ const& other ) noexcept
+{
+	array_ = other.array_;
+	pos_ = other.pos_;
+	return *this;
+}
+
+/*----------------------------------------------------------------------------*/
+
+template< typename T , ptrdiff_t D>
+inline void swap(
+		M_CNAME_T_& lhs ,
+		M_CNAME_T_& rhs ) noexcept
+{
+	std::swap( lhs.array_ , rhs.array_ );
+	std::swap( lhs.pos_ , rhs.pos_ );
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::operator==(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ == other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator!=(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ != other.array_ || pos_ != other.pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::operator <(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ < other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator<=(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ <= other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator >(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ > other.pos_;
+}
+
+M_HDR_ inline bool M_CNAME_::operator>=(
+		T_ConstIterator_ const& other ) const noexcept
+{
+	return array_ == other.array_ && pos_ >= other.pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline T const& M_CNAME_::operator*( ) const noexcept
+{
+	assert( valid( ) );
+	return (*array_)[ pos_ ];
+}
+
+M_HDR_ inline T const* M_CNAME_::operator->( ) const noexcept
+{
+	assert( valid( ) );
+	return &((*array_)[ pos_ ]);
+}
+
+M_HDR_ inline T const& M_CNAME_::operator[](
+		const ptrdiff_t pos ) const noexcept
+{
+	const auto idx( pos + pos_ );
+	assert( array_ && idx >= 0 && idx < array_->size( ) );
+	return (*array_)[ idx ];
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator++ () noexcept
+{
+	assert( valid( ) );
+	pos_ += D;
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator++ (int) noexcept
+{
+	assert( valid( ) );
+	auto copy( *this );
+	pos_ += D;
+	return copy;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator-- () noexcept
+{
+	assert( valid( ) );
+	pos_ -= D;
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator-- (int) noexcept
+{
+	assert( valid( ) );
+	auto copy( *this );
+	pos_ -= D;
+	return copy;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator +(
+		const ptrdiff_t value ) const noexcept
+{
+	auto copy( *this );
+	copy += value;
+	return copy;
+}
+
+M_HDR_ inline M_CNAME_T_ M_CNAME_::operator -(
+		const ptrdiff_t value ) const noexcept
+{
+	auto copy( *this );
+	copy -= value;
+	return copy;
+}
+
+M_HDR_ inline ptrdiff_t M_CNAME_::operator -(
+		M_CNAME_T_ const& other ) const noexcept
+{
+	assert( array_ && array_ == other.array_ );
+	return pos_ - other.pos_;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator +=(
+		const ptrdiff_t value ) noexcept
+{
+	assert( valid( ) );
+	pos_ = std::min( ptrdiff_t( array_->size( ) ) ,
+		std::max( ptrdiff_t( -1 ) , pos_ + value * D ) );
+	return *this;
+}
+
+M_HDR_ inline M_CNAME_T_& M_CNAME_::operator -=(
+		const ptrdiff_t value ) noexcept
+{
+	assert( valid( ) );
+	pos_ = std::min( ptrdiff_t( array_->size( ) ) ,
+		std::max( ptrdiff_t( -1 ) , pos_ - value * D ) );
+	return *this;
+}
+
+/*----------------------------------------------------------------------------*/
+
+M_HDR_ inline bool M_CNAME_::valid( ) const noexcept
+{
+	return array_ && pos_ >= 0 && pos_ < array_->size( );
+}
+
+M_HDR_ inline T_Array< T >* M_CNAME_::target( ) const noexcept
+{
+	return array_;
+}
+
+M_HDR_ inline ptrdiff_t M_CNAME_::pos( ) const noexcept
+{
+	return pos_;
+}
+
+/*----------------------------------------------------------------------------*/
+
+#undef M_HDR_
+#undef M_CNAME_
+#undef M_CNAME_T_
 
 /*= T_StaticArray ============================================================*/
 
diff --git a/tests/arrays-iter.cc b/tests/arrays-iter.cc
new file mode 100644
index 0000000..aa97e36
--- /dev/null
+++ b/tests/arrays-iter.cc
@@ -0,0 +1,822 @@
+#include <ebcl/Arrays.hh>
+#include <cppunit/extensions/HelperMacros.h>
+using namespace ebcl;
+
+
+class ArraysIterTest : public CppUnit::TestFixture
+{
+	CPPUNIT_TEST_SUITE( ArraysIterTest );
+		CPPUNIT_TEST( testConstructDefault );
+		CPPUNIT_TEST( testConstructFromArray );
+		CPPUNIT_TEST( testCopyCons );
+		CPPUNIT_TEST( testCopyAss );
+		CPPUNIT_TEST( testSwap );
+
+		CPPUNIT_TEST( testArrayIterator );
+		CPPUNIT_TEST( testArrayReverse );
+
+		CPPUNIT_TEST( testDerefStar );
+		CPPUNIT_TEST( testDerefArrow );
+		CPPUNIT_TEST( testDerefOffset );
+
+		CPPUNIT_TEST( testCmpEq );
+		CPPUNIT_TEST( testCmpNe );
+		CPPUNIT_TEST( testCmpLt );
+		CPPUNIT_TEST( testCmpLe );
+		CPPUNIT_TEST( testCmpGt );
+		CPPUNIT_TEST( testCmpGe );
+
+		CPPUNIT_TEST( testPreIncrement );
+		CPPUNIT_TEST( testPostIncrement );
+		CPPUNIT_TEST( testPreDecrement );
+		CPPUNIT_TEST( testPostDecrement );
+
+		CPPUNIT_TEST( testPreIncrementReverse );
+		CPPUNIT_TEST( testPostIncrementReverse );
+		CPPUNIT_TEST( testPreDecrementReverse );
+		CPPUNIT_TEST( testPostDecrementReverse );
+
+		CPPUNIT_TEST( testAddTo );
+		CPPUNIT_TEST( testAddToReverse );
+		CPPUNIT_TEST( testSubTo );
+		CPPUNIT_TEST( testSubToReverse );
+
+		CPPUNIT_TEST( testAdd );
+		CPPUNIT_TEST( testAddReverse );
+		CPPUNIT_TEST( testSub );
+		CPPUNIT_TEST( testSubReverse );
+		CPPUNIT_TEST( testDifference );
+	CPPUNIT_TEST_SUITE_END( );
+
+    public:
+	void testConstructDefault( );
+	void testConstructFromArray( );
+	void testCopyCons( );
+	void testCopyAss( );
+	void testSwap( );
+
+	void testArrayIterator( );
+	void testArrayReverse( );
+
+	void testDerefStar( );
+	void testDerefArrow( );
+	void testDerefOffset( );
+
+	void testCmpEq( );
+	void testCmpNe( );
+	void testCmpLt( );
+	void testCmpLe( );
+	void testCmpGt( );
+	void testCmpGe( );
+
+	void testPreIncrement( );
+	void testPostIncrement( );
+	void testPreDecrement( );
+	void testPostDecrement( );
+
+	void testPreIncrementReverse( );
+	void testPostIncrementReverse( );
+	void testPreDecrementReverse( );
+	void testPostDecrementReverse( );
+
+	void testAddTo( );
+	void testAddToReverse( );
+	void testSubTo( );
+	void testSubToReverse( );
+
+	void testAdd( );
+	void testAddReverse( );
+	void testSub( );
+	void testSubReverse( );
+	void testDifference( );
+};
+CPPUNIT_TEST_SUITE_REGISTRATION( ArraysIterTest );
+
+using T_Test_ = T_Array< int >;
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testConstructDefault( )
+{
+	T_Test_::T_Iterator iter;
+	CPPUNIT_ASSERT( !iter.valid( ) );
+}
+
+void ArraysIterTest::testConstructFromArray( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter( x , 1 );
+	CPPUNIT_ASSERT( iter.valid( ) );
+	CPPUNIT_ASSERT( iter.target( ) == &x );
+	CPPUNIT_ASSERT( iter.pos( ) == 1 );
+}
+
+void ArraysIterTest::testCopyCons( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter( x , 1 );
+	T_Test_::T_Iterator iter2( iter );
+	iter = {};
+
+	CPPUNIT_ASSERT( iter2.valid( ) );
+	CPPUNIT_ASSERT( iter2.target( ) == &x );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+void ArraysIterTest::testCopyAss( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter( x , 1 );
+	T_Test_::T_Iterator iter2;
+	iter2 = iter;
+	iter = {};
+
+	CPPUNIT_ASSERT( iter2.valid( ) );
+	CPPUNIT_ASSERT( iter2.target( ) == &x );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+void ArraysIterTest::testSwap( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter( x , 1 );
+	T_Test_::T_Iterator iter2;
+	swap( iter , iter2 );
+
+	CPPUNIT_ASSERT( !iter.valid( ) );
+	CPPUNIT_ASSERT( iter.target( ) == nullptr );
+	CPPUNIT_ASSERT( iter.pos( ) == 0 );
+
+	CPPUNIT_ASSERT( iter2.valid( ) );
+	CPPUNIT_ASSERT( iter2.target( ) == &x );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testArrayIterator( )
+{
+	T_Test_ x;
+	x.add( 1 );
+
+	T_Test_::T_Iterator it1( x.begin( ) );
+	T_Test_::T_Iterator it2( x.end( ) );
+
+	CPPUNIT_ASSERT( &x == it1.target( ) );
+	CPPUNIT_ASSERT( &x == it2.target( ) );
+
+	CPPUNIT_ASSERT( 0 == it1.pos( ) );
+	CPPUNIT_ASSERT( x.size( ) == it2.pos( ) );
+}
+
+void ArraysIterTest::testArrayReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+
+	T_Test_::T_ReverseIterator it1( x.rbegin( ) );
+	T_Test_::T_ReverseIterator it2( x.rend( ) );
+
+	CPPUNIT_ASSERT( &x == it1.target( ) );
+	CPPUNIT_ASSERT( &x == it2.target( ) );
+
+	CPPUNIT_ASSERT( x.size( ) - 1 == it1.pos( ) );
+	CPPUNIT_ASSERT( -1 == it2.pos( ) );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testDerefStar( )
+{
+	T_Test_ x;
+	x.add( 1 );
+
+	T_Test_::T_Iterator it( x , 0 );
+	CPPUNIT_ASSERT_EQUAL( 1 , *it );
+}
+
+void ArraysIterTest::testDerefArrow( )
+{
+	struct T_Obj_ {
+		int x;
+		T_Obj_( int x ) : x( x ) { }
+		int value( ) const noexcept { return x; }
+	};
+	using T_Test_ = T_Array< T_Obj_ >;
+
+	T_Test_ t;
+	t.add( 42 );
+
+	T_Test_::T_Iterator it( t , 0 );
+	CPPUNIT_ASSERT_EQUAL( 42 , it->value( ) );
+}
+
+void ArraysIterTest::testDerefOffset( )
+{
+	T_Test_ x;
+	x.add( 0 );
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator it( x , 1 );
+	CPPUNIT_ASSERT_EQUAL( 0 , it[ -1 ] );
+	CPPUNIT_ASSERT_EQUAL( 1 , it[ 0 ] );
+	CPPUNIT_ASSERT_EQUAL( 2 , it[ 1 ] );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testCmpEq( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT( iter1 == iter1 );
+	CPPUNIT_ASSERT( iter1 == iter2 );
+	CPPUNIT_ASSERT( !( iter1 == iter3 ) );
+	CPPUNIT_ASSERT( !( iter1 == iter4 ) );
+	CPPUNIT_ASSERT( !( iter1 == iter5 ) );
+	CPPUNIT_ASSERT( !( iter1 == iter6 ) );
+
+	CPPUNIT_ASSERT( iter2 == iter1 );
+	CPPUNIT_ASSERT( iter2 == iter2 );
+	CPPUNIT_ASSERT( !( iter2 == iter3 ) );
+	CPPUNIT_ASSERT( !( iter2 == iter4 ) );
+	CPPUNIT_ASSERT( !( iter2 == iter5 ) );
+	CPPUNIT_ASSERT( !( iter2 == iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter3 == iter1 ) );
+	CPPUNIT_ASSERT( !( iter3 == iter2 ) );
+	CPPUNIT_ASSERT( iter3 == iter3 );
+	CPPUNIT_ASSERT( !( iter3 == iter4 ) );
+	CPPUNIT_ASSERT( iter3 == iter5 );
+	CPPUNIT_ASSERT( !( iter3 == iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter4 == iter1 ) );
+	CPPUNIT_ASSERT( !( iter4 == iter2 ) );
+	CPPUNIT_ASSERT( !( iter4 == iter3 ) );
+	CPPUNIT_ASSERT( iter4 == iter4 );
+	CPPUNIT_ASSERT( !( iter4 == iter5 ) );
+	CPPUNIT_ASSERT( !( iter4 == iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter5 == iter1 ) );
+	CPPUNIT_ASSERT( !( iter5 == iter2 ) );
+	CPPUNIT_ASSERT( iter5 == iter3 );
+	CPPUNIT_ASSERT( !( iter5 == iter4 ) );
+	CPPUNIT_ASSERT( iter5 == iter5 );
+	CPPUNIT_ASSERT( !( iter5 == iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter6 == iter1 ) );
+	CPPUNIT_ASSERT( !( iter6 == iter2 ) );
+	CPPUNIT_ASSERT( !( iter6 == iter3 ) );
+	CPPUNIT_ASSERT( !( iter6 == iter4 ) );
+	CPPUNIT_ASSERT( !( iter6 == iter5 ) );
+	CPPUNIT_ASSERT( iter6 == iter6 );
+}
+
+void ArraysIterTest::testCmpNe( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT( !( iter1 != iter1 ) );
+	CPPUNIT_ASSERT( !( iter1 != iter2 ) );
+	CPPUNIT_ASSERT( iter1 != iter3 );
+	CPPUNIT_ASSERT( iter1 != iter4 );
+	CPPUNIT_ASSERT( iter1 != iter5 );
+	CPPUNIT_ASSERT( iter1 != iter6 );
+
+	CPPUNIT_ASSERT( !( iter2 != iter1 ) );
+	CPPUNIT_ASSERT( !( iter2 != iter2 ) );
+	CPPUNIT_ASSERT( iter2 != iter3 );
+	CPPUNIT_ASSERT( iter2 != iter4 );
+	CPPUNIT_ASSERT( iter2 != iter5 );
+	CPPUNIT_ASSERT( iter2 != iter6 );
+
+	CPPUNIT_ASSERT( iter3 != iter1 );
+	CPPUNIT_ASSERT( iter3 != iter2 );
+	CPPUNIT_ASSERT( !( iter3 != iter3 ) );
+	CPPUNIT_ASSERT( iter3 != iter4 );
+	CPPUNIT_ASSERT( !( iter3 != iter5 ) );
+	CPPUNIT_ASSERT( iter3 != iter6 );
+
+	CPPUNIT_ASSERT( iter4 != iter1 );
+	CPPUNIT_ASSERT( iter4 != iter2 );
+	CPPUNIT_ASSERT( iter4 != iter3 );
+	CPPUNIT_ASSERT( !( iter4 != iter4 ) );
+	CPPUNIT_ASSERT( iter4 != iter5 );
+	CPPUNIT_ASSERT( iter4 != iter6 );
+
+	CPPUNIT_ASSERT( iter5 != iter1 );
+	CPPUNIT_ASSERT( iter5 != iter2 );
+	CPPUNIT_ASSERT( !( iter5 != iter3 ) );
+	CPPUNIT_ASSERT( iter5 != iter4 );
+	CPPUNIT_ASSERT( !( iter5 != iter5 ) );
+	CPPUNIT_ASSERT( iter5 != iter6 );
+
+	CPPUNIT_ASSERT( iter6 != iter1 );
+	CPPUNIT_ASSERT( iter6 != iter2 );
+	CPPUNIT_ASSERT( iter6 != iter3 );
+	CPPUNIT_ASSERT( iter6 != iter4 );
+	CPPUNIT_ASSERT( iter6 != iter5 );
+	CPPUNIT_ASSERT( !( iter6 != iter6 ) );
+}
+
+void ArraysIterTest::testCmpLt( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT( !( iter1 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter1 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter1 < iter3 ) );
+	CPPUNIT_ASSERT(    iter1 < iter4   );
+	CPPUNIT_ASSERT( !( iter1 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter1 < iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter2 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter2 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter2 < iter3 ) );
+	CPPUNIT_ASSERT(    iter2 < iter4   );
+	CPPUNIT_ASSERT( !( iter2 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter2 < iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter3 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter3 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter3 < iter3 ) );
+	CPPUNIT_ASSERT( !( iter3 < iter4 ) );
+	CPPUNIT_ASSERT( !( iter3 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter3 < iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter4 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter4 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter4 < iter3 ) );
+	CPPUNIT_ASSERT( !( iter4 < iter4 ) );
+	CPPUNIT_ASSERT( !( iter4 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter4 < iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter5 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter5 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter5 < iter3 ) );
+	CPPUNIT_ASSERT( !( iter5 < iter4 ) );
+	CPPUNIT_ASSERT( !( iter5 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter5 < iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter6 < iter1 ) );
+	CPPUNIT_ASSERT( !( iter6 < iter2 ) );
+	CPPUNIT_ASSERT( !( iter6 < iter3 ) );
+	CPPUNIT_ASSERT( !( iter6 < iter4 ) );
+	CPPUNIT_ASSERT( !( iter6 < iter5 ) );
+	CPPUNIT_ASSERT( !( iter6 < iter6 ) );
+}
+
+void ArraysIterTest::testCmpLe( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT(    iter1 <= iter1   );
+	CPPUNIT_ASSERT(    iter1 <= iter2   );
+	CPPUNIT_ASSERT( !( iter1 <= iter3 ) );
+	CPPUNIT_ASSERT(    iter1 <= iter4   );
+	CPPUNIT_ASSERT( !( iter1 <= iter5 ) );
+	CPPUNIT_ASSERT( !( iter1 <= iter6 ) );
+
+	CPPUNIT_ASSERT(    iter2 <= iter1   );
+	CPPUNIT_ASSERT(    iter2 <= iter2   );
+	CPPUNIT_ASSERT( !( iter2 <= iter3 ) );
+	CPPUNIT_ASSERT(    iter2 <= iter4   );
+	CPPUNIT_ASSERT( !( iter2 <= iter5 ) );
+	CPPUNIT_ASSERT( !( iter2 <= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter3 <= iter1 ) );
+	CPPUNIT_ASSERT( !( iter3 <= iter2 ) );
+	CPPUNIT_ASSERT(    iter3 <= iter3   );
+	CPPUNIT_ASSERT( !( iter3 <= iter4 ) );
+	CPPUNIT_ASSERT(    iter3 <= iter5   );
+	CPPUNIT_ASSERT( !( iter3 <= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter4 <= iter1 ) );
+	CPPUNIT_ASSERT( !( iter4 <= iter2 ) );
+	CPPUNIT_ASSERT( !( iter4 <= iter3 ) );
+	CPPUNIT_ASSERT(    iter4 <= iter4   );
+	CPPUNIT_ASSERT( !( iter4 <= iter5 ) );
+	CPPUNIT_ASSERT( !( iter4 <= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter5 <= iter1 ) );
+	CPPUNIT_ASSERT( !( iter5 <= iter2 ) );
+	CPPUNIT_ASSERT(    iter5 <= iter3   );
+	CPPUNIT_ASSERT( !( iter5 <= iter4 ) );
+	CPPUNIT_ASSERT(    iter5 <= iter5   );
+	CPPUNIT_ASSERT( !( iter5 <= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter6 <= iter1 ) );
+	CPPUNIT_ASSERT( !( iter6 <= iter2 ) );
+	CPPUNIT_ASSERT( !( iter6 <= iter3 ) );
+	CPPUNIT_ASSERT( !( iter6 <= iter4 ) );
+	CPPUNIT_ASSERT( !( iter6 <= iter5 ) );
+	CPPUNIT_ASSERT(    iter6 <= iter6   );
+}
+
+void ArraysIterTest::testCmpGt( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT( !( iter1 > iter1 ) );
+	CPPUNIT_ASSERT( !( iter1 > iter2 ) );
+	CPPUNIT_ASSERT( !( iter1 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter1 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter1 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter1 > iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter2 > iter1 ) );
+	CPPUNIT_ASSERT( !( iter2 > iter2 ) );
+	CPPUNIT_ASSERT( !( iter2 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter2 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter2 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter2 > iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter3 > iter1 ) );
+	CPPUNIT_ASSERT( !( iter3 > iter2 ) );
+	CPPUNIT_ASSERT( !( iter3 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter3 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter3 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter3 > iter6 ) );
+
+	CPPUNIT_ASSERT(    iter4 > iter1   );
+	CPPUNIT_ASSERT(    iter4 > iter2   );
+	CPPUNIT_ASSERT( !( iter4 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter4 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter4 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter4 > iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter5 > iter1 ) );
+	CPPUNIT_ASSERT( !( iter5 > iter2 ) );
+	CPPUNIT_ASSERT( !( iter5 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter5 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter5 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter5 > iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter6 > iter1 ) );
+	CPPUNIT_ASSERT( !( iter6 > iter2 ) );
+	CPPUNIT_ASSERT( !( iter6 > iter3 ) );
+	CPPUNIT_ASSERT( !( iter6 > iter4 ) );
+	CPPUNIT_ASSERT( !( iter6 > iter5 ) );
+	CPPUNIT_ASSERT( !( iter6 > iter6 ) );
+}
+
+void ArraysIterTest::testCmpGe( )
+{
+	T_Test_ x , x2;
+	x.add( 1 );
+	x.add( 2 );
+	x2.add( 3 );
+
+	T_Test_::T_Iterator iter1( x , 0 ) ,
+		iter2( x , 0 ) ,
+		iter3 ,
+		iter4( x , 1 ) ,
+		iter5 ,
+		iter6( x2 , 0 );
+
+	CPPUNIT_ASSERT(    iter1 >= iter1   );
+	CPPUNIT_ASSERT(    iter1 >= iter2   );
+	CPPUNIT_ASSERT( !( iter1 >= iter3 ) );
+	CPPUNIT_ASSERT( !( iter1 >= iter4 ) );
+	CPPUNIT_ASSERT( !( iter1 >= iter5 ) );
+	CPPUNIT_ASSERT( !( iter1 >= iter6 ) );
+
+	CPPUNIT_ASSERT(    iter2 >= iter1   );
+	CPPUNIT_ASSERT(    iter2 >= iter2   );
+	CPPUNIT_ASSERT( !( iter2 >= iter3 ) );
+	CPPUNIT_ASSERT( !( iter2 >= iter4 ) );
+	CPPUNIT_ASSERT( !( iter2 >= iter5 ) );
+	CPPUNIT_ASSERT( !( iter2 >= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter3 >= iter1 ) );
+	CPPUNIT_ASSERT( !( iter3 >= iter2 ) );
+	CPPUNIT_ASSERT(    iter3 >= iter3   );
+	CPPUNIT_ASSERT( !( iter3 >= iter4 ) );
+	CPPUNIT_ASSERT(    iter3 >= iter5   );
+	CPPUNIT_ASSERT( !( iter3 >= iter6 ) );
+
+	CPPUNIT_ASSERT(    iter4 >= iter1   );
+	CPPUNIT_ASSERT(    iter4 >= iter2   );
+	CPPUNIT_ASSERT( !( iter4 >= iter3 ) );
+	CPPUNIT_ASSERT(    iter4 >= iter4   );
+	CPPUNIT_ASSERT( !( iter4 >= iter5 ) );
+	CPPUNIT_ASSERT( !( iter4 >= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter5 >= iter1 ) );
+	CPPUNIT_ASSERT( !( iter5 >= iter2 ) );
+	CPPUNIT_ASSERT(    iter5 >= iter3   );
+	CPPUNIT_ASSERT( !( iter5 >= iter4 ) );
+	CPPUNIT_ASSERT(    iter5 >= iter5   );
+	CPPUNIT_ASSERT( !( iter5 >= iter6 ) );
+
+	CPPUNIT_ASSERT( !( iter6 >= iter1 ) );
+	CPPUNIT_ASSERT( !( iter6 >= iter2 ) );
+	CPPUNIT_ASSERT( !( iter6 >= iter3 ) );
+	CPPUNIT_ASSERT( !( iter6 >= iter4 ) );
+	CPPUNIT_ASSERT( !( iter6 >= iter5 ) );
+	CPPUNIT_ASSERT(    iter6 >= iter6   );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testPreIncrement( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter1( x , 0 );
+	T_Test_::T_Iterator iter2( ++iter1 );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 1 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+void ArraysIterTest::testPostIncrement( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter1( x , 0 );
+	T_Test_::T_Iterator iter2( iter1++ );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 1 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 0 );
+}
+
+void ArraysIterTest::testPreDecrement( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter1( x , 1 );
+	T_Test_::T_Iterator iter2( --iter1 );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 0 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 0 );
+}
+
+void ArraysIterTest::testPostDecrement( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_Iterator iter1( x , 1 );
+	T_Test_::T_Iterator iter2( iter1-- );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 0 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testPreIncrementReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_ReverseIterator iter1( x , 1 );
+	T_Test_::T_ReverseIterator iter2( ++iter1 );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 0 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 0 );
+}
+
+void ArraysIterTest::testPostIncrementReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_ReverseIterator iter1( x , 1 );
+	T_Test_::T_ReverseIterator iter2( iter1++ );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 0 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+void ArraysIterTest::testPreDecrementReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_ReverseIterator iter1( x , 0 );
+	T_Test_::T_ReverseIterator iter2( --iter1 );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 1 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 1 );
+}
+
+void ArraysIterTest::testPostDecrementReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+
+	T_Test_::T_ReverseIterator iter1( x , 0 );
+	T_Test_::T_ReverseIterator iter2( iter1-- );
+
+	CPPUNIT_ASSERT( iter1.pos( ) == 1 );
+	CPPUNIT_ASSERT( iter2.pos( ) == 0 );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testAddTo( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_Iterator it( x , 0 );
+	it += 2;
+	CPPUNIT_ASSERT( it.pos( ) == 2 );
+	it += 2;
+	CPPUNIT_ASSERT( it.pos( ) == 3 );
+}
+
+void ArraysIterTest::testAddToReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_ReverseIterator it( x.rbegin( ) );
+	it += 2;
+	CPPUNIT_ASSERT( it.pos( ) == 0 );
+	it += 2;
+	CPPUNIT_ASSERT( it.pos( ) == -1 );
+}
+
+void ArraysIterTest::testSubTo( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_Iterator it( x , x.size( ) - 1 );
+	it -= 2;
+	CPPUNIT_ASSERT( it.pos( ) == 0 );
+	it -= 2;
+	CPPUNIT_ASSERT( it.pos( ) == -1 );
+}
+
+void ArraysIterTest::testSubToReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_ReverseIterator it( x , 0 );
+	it -= 2;
+	CPPUNIT_ASSERT( it.pos( ) == 2 );
+	it -= 2;
+	CPPUNIT_ASSERT( it.pos( ) == 3 );
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ArraysIterTest::testAdd( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_Iterator it( x , 0 );
+	auto it2( it + 4 );
+	CPPUNIT_ASSERT( it.pos( ) == 0 );
+	CPPUNIT_ASSERT( it2.target( ) == &x );
+	CPPUNIT_ASSERT( it2.pos( ) == 3 );
+	CPPUNIT_ASSERT( it2 == x.end( ) );
+}
+
+void ArraysIterTest::testAddReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_ReverseIterator it( x.rbegin( ) );
+	auto it2( it + 4 );
+	CPPUNIT_ASSERT( it.pos( ) == 2 );
+	CPPUNIT_ASSERT( it2.target( ) == &x );
+	CPPUNIT_ASSERT( it2.pos( ) == -1 );
+	CPPUNIT_ASSERT( it2 == x.rend( ) );
+}
+
+void ArraysIterTest::testSub( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_Iterator it( x , x.size( ) - 1 );
+	auto it2( it - 4 );
+	CPPUNIT_ASSERT( it.pos( ) == 2 );
+	CPPUNIT_ASSERT( it2.target( ) == &x );
+	CPPUNIT_ASSERT( it2.pos( ) == -1 );
+}
+
+void ArraysIterTest::testSubReverse( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_ReverseIterator it( x , 0 );
+	auto it2( it - 4 );
+	CPPUNIT_ASSERT( it.pos( ) == 0 );
+	CPPUNIT_ASSERT( it2.target( ) == &x );
+	CPPUNIT_ASSERT( it2.pos( ) == 3 );
+}
+
+void ArraysIterTest::testDifference( )
+{
+	T_Test_ x;
+	x.add( 1 );
+	x.add( 2 );
+	x.add( 3 );
+
+	T_Test_::T_Iterator it( x.begin( ) );
+	T_Test_::T_Iterator it2( x.end( ) );
+	const auto diff1( it2 - it );
+	CPPUNIT_ASSERT( diff1 == x.size( ) );
+	const auto diff2( it - it2 );
+	CPPUNIT_ASSERT( -diff2 == x.size( ) );
+}
diff --git a/tests/list.mk b/tests/list.mk
index e6ddbc5..53fc34b 100644
--- a/tests/list.mk
+++ b/tests/list.mk
@@ -7,6 +7,7 @@ TESTS = \
 	ptr-weak \
 	arrays-basic \
 	arrays-objects \
+	arrays-iter \
 	arrays-static-basic \
 	arrays-static-objects \
 	arrays-auto \