Arrays - C++-style iterators

This commit is contained in:
Emmanuel BENOîT 2017-11-02 14:23:19 +01:00
parent 2e8092af9a
commit 90048ad3cc
5 changed files with 1444 additions and 0 deletions

View file

@ -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

View file

@ -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 =========================================================*/
/*

View file

@ -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 ============================================================*/