mirror of
https://github.com/boostorg/dynamic_bitset.git
synced 2026-01-19 04:12:09 +00:00
Add C++20 iterators
Reason: Requested on the mailing list.
This commit is contained in:
@@ -46,22 +46,12 @@ an unsigned long `n`, the bit at position `i` of the bitset has the same value
|
||||
as `(n >> i) & 1`.
|
||||
|
||||
== Rationale
|
||||
`dynamic_bitset` is not a <a
|
||||
Because of the proxy reference type, `dynamic_bitset` is not a <a
|
||||
href="https://en.cppreference.com/w/cpp/named_req/Container.html">Container</a>
|
||||
and does not provide iterators for the following reason:
|
||||
|
||||
A container with a proxy reference type can not fulfill the container
|
||||
requirements as specified in the C++ standard (unless one resorts to strange
|
||||
iterator semantics). `std::vector<bool>` has a proxy reference type and does not
|
||||
fulfill the container requirements and as a result has caused many problems. One
|
||||
common problem is when people try to use iterators from `std::vector<bool>` with
|
||||
a standard algorithm such as `std::search()`. The `std::search()` requirements
|
||||
say that the iterator must be a LegacyForwardIterator, but
|
||||
`std::vector<bool>::iterator` does not meet this requirement because of the
|
||||
proxy reference. Depending on the implementation, they may or not be a compile
|
||||
error or even a run-time error due to this misuse. For further discussion of the
|
||||
problem see "Effective STL" by Scott Meyers. So `dynamic_bitset` tries to avoid
|
||||
these problems by not pretending to be a container.
|
||||
and its iterators do not satisfy the requirements for a LegacyForwardIterator.
|
||||
This means that its iterators are not usable with many standard algorithms.
|
||||
However, `dynamic_bitset` provides C++20 iterators which can be used with
|
||||
ranges.
|
||||
|
||||
Some people prefer the name "toggle" to "flip". The name "flip" was chosen
|
||||
because that is the name used in `std::bitset`. In fact, most of the function
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "boost/dynamic_bitset_fwd.hpp"
|
||||
#include "boost/limits.hpp"
|
||||
#include "boost/static_assert.hpp"
|
||||
#if __cpp_lib_three_way_comparison
|
||||
#include <compare>
|
||||
#endif
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -45,6 +48,15 @@ struct hash< boost::dynamic_bitset< Block, AllocatorOrContainer > >;
|
||||
|
||||
namespace boost {
|
||||
|
||||
template< typename Iterator >
|
||||
class bit_iterator_base;
|
||||
|
||||
template< typename DynamicBitset >
|
||||
class bit_iterator;
|
||||
|
||||
template< typename DynamicBitset >
|
||||
class const_bit_iterator;
|
||||
|
||||
//! The `dynamic_bitset` template represents a set of bits.
|
||||
//!
|
||||
//! \par Template parameters
|
||||
@@ -65,7 +77,8 @@ namespace boost {
|
||||
//! `Block` is a cv-unqualified unsigned integer type other than
|
||||
//! `bool`. `AllocatorOrContainer` satisfies the standard requirements for an
|
||||
//! <a href="https://en.cppreference.com/w/cpp/named_req/Allocator.html">allocator</a>
|
||||
//! or is a container-like type.
|
||||
//! or is a container-like type which provides at least bidirectional
|
||||
//! iterators.
|
||||
// ---------------------------------------------------------------------------
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
class dynamic_bitset
|
||||
@@ -251,6 +264,25 @@ public:
|
||||
// -----------------------------------------------------------------------
|
||||
typedef bool const_reference;
|
||||
|
||||
friend class bit_iterator< dynamic_bitset >;
|
||||
friend class const_bit_iterator< dynamic_bitset >;
|
||||
|
||||
//! A read/write iterator into the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
typedef bit_iterator< dynamic_bitset > iterator;
|
||||
|
||||
//! A read-only iterator into the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
typedef const_bit_iterator< dynamic_bitset > const_iterator;
|
||||
|
||||
//! A reverse read/write reverse iterator into the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
typedef std::reverse_iterator< iterator > reverse_iterator;
|
||||
|
||||
//! A reverse read-only iterator into the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
|
||||
|
||||
//! Constructs a bitset of size zero.
|
||||
//!
|
||||
//! \par Postconditions
|
||||
@@ -446,6 +478,66 @@ public:
|
||||
// -----------------------------------------------------------------------
|
||||
~dynamic_bitset();
|
||||
|
||||
//! Returns a read/write iterator that refers to the least
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
iterator begin();
|
||||
|
||||
//! Returns a read-only iterator that refers to the least
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_iterator begin() const;
|
||||
|
||||
//! Returns a read/write iterator that refers one past the most
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
iterator end();
|
||||
|
||||
//! Returns a read-only iterator that refers one past the most
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_iterator end() const;
|
||||
|
||||
//! Returns a read/write reverse iterator that refers to the
|
||||
//! most significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
reverse_iterator rbegin();
|
||||
|
||||
//! Returns a read-only reverse iterator that refers to the most
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_reverse_iterator rbegin() const;
|
||||
|
||||
//! Returns a read/write reverse iterator that refers to one
|
||||
//! before the least significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
reverse_iterator rend();
|
||||
|
||||
//! Returns a read-only reverse iterator that refers to one
|
||||
//! before the least significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_reverse_iterator rend() const;
|
||||
|
||||
//! Returns a read-only iterator that refers to the least
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_iterator cbegin() const;
|
||||
|
||||
//! Returns a read-only iterator that refers to one past the
|
||||
//! most significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_iterator cend() const;
|
||||
|
||||
//! Returns a read-only reverse iterator that refers to the most
|
||||
//! significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_reverse_iterator crbegin() const;
|
||||
|
||||
//! Returns a read-only reverse iterator that refers to one
|
||||
//! before the least significant bit in the bitset.
|
||||
// -----------------------------------------------------------------------
|
||||
const_reverse_iterator crend() const;
|
||||
|
||||
//! Swaps the contents of this bitset and bitset `b`.
|
||||
//!
|
||||
//! \param b The bitset to be swapped with `*this`.
|
||||
@@ -1266,6 +1358,72 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
template< typename Iterator >
|
||||
class bit_iterator_base
|
||||
{
|
||||
public:
|
||||
typedef typename Iterator::iterator_category iterator_category;
|
||||
typedef bool value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef value_type * pointer;
|
||||
typedef value_type & reference;
|
||||
|
||||
bit_iterator_base( Iterator block_iterator, int bit_index );
|
||||
|
||||
void increment();
|
||||
void decrement();
|
||||
void add( typename Iterator::difference_type n );
|
||||
|
||||
BOOST_STATIC_CONSTANT( int, bits_per_block = std::numeric_limits< typename Iterator::value_type >::digits );
|
||||
Iterator m_block_iterator;
|
||||
int m_bit_index = 0;
|
||||
};
|
||||
|
||||
template< typename DynamicBitset >
|
||||
class bit_iterator
|
||||
: public bit_iterator_base< typename DynamicBitset::buffer_type::iterator >
|
||||
{
|
||||
public:
|
||||
typedef typename DynamicBitset::reference reference;
|
||||
typedef reference * pointer;
|
||||
typedef typename bit_iterator_base< typename DynamicBitset::buffer_type::iterator >::difference_type difference_type;
|
||||
|
||||
bit_iterator();
|
||||
bit_iterator( typename DynamicBitset::buffer_type::iterator block_iterator, int bit_index );
|
||||
|
||||
reference operator*() const;
|
||||
bit_iterator & operator++();
|
||||
bit_iterator operator++( int );
|
||||
bit_iterator & operator--();
|
||||
bit_iterator operator--( int );
|
||||
bit_iterator & operator+=( difference_type n );
|
||||
bit_iterator & operator-=( difference_type n );
|
||||
reference operator[]( difference_type n ) const;
|
||||
};
|
||||
|
||||
template< typename DynamicBitset >
|
||||
class const_bit_iterator
|
||||
: public bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >
|
||||
{
|
||||
public:
|
||||
typedef bool reference;
|
||||
typedef bool const_reference;
|
||||
typedef const bool * pointer;
|
||||
typedef typename bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >::difference_type difference_type;
|
||||
|
||||
const_bit_iterator( typename DynamicBitset::buffer_type::const_iterator block_iterator, int bit_index );
|
||||
const_bit_iterator( const bit_iterator< DynamicBitset > & it );
|
||||
|
||||
const_reference operator*() const;
|
||||
const_bit_iterator & operator++();
|
||||
const_bit_iterator operator++( int );
|
||||
const_bit_iterator & operator--();
|
||||
const_bit_iterator operator--( int );
|
||||
const_bit_iterator & operator+=( difference_type n );
|
||||
const_bit_iterator & operator-=( difference_type n );
|
||||
const_reference operator[]( difference_type n ) const;
|
||||
};
|
||||
|
||||
#if ! defined BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
@@ -1280,6 +1438,9 @@ template< typename Block, typename AllocatorOrContainer >
|
||||
const int
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::ulong_width;
|
||||
|
||||
template< typename Container >
|
||||
const int
|
||||
bit_iterator_base< Container >::bits_per_block;
|
||||
#endif
|
||||
|
||||
//! Compares two bitsets.
|
||||
|
||||
@@ -155,6 +155,319 @@ dynamic_bitset< Block, AllocatorOrContainer >::reference::do_assign( bool x )
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bit_iterator_base< Iterator >::bit_iterator_base( Iterator block_iterator, int bit_index )
|
||||
: m_block_iterator( block_iterator )
|
||||
, m_bit_index( bit_index )
|
||||
{
|
||||
BOOST_ASSERT( 0 <= bit_index && bit_index < bits_per_block );
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
void
|
||||
bit_iterator_base< Iterator >::increment()
|
||||
{
|
||||
++m_bit_index;
|
||||
if ( m_bit_index == bits_per_block ) {
|
||||
m_bit_index = 0;
|
||||
++m_block_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
void
|
||||
bit_iterator_base< Iterator >::decrement()
|
||||
{
|
||||
--m_bit_index;
|
||||
if ( m_bit_index < 0 ) {
|
||||
m_bit_index = bits_per_block - 1;
|
||||
--m_block_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
void
|
||||
bit_iterator_base< Iterator >::add( typename Iterator::difference_type n )
|
||||
{
|
||||
typename Iterator::difference_type d = m_bit_index + n;
|
||||
m_block_iterator += d / bits_per_block;
|
||||
d %= bits_per_block;
|
||||
if ( d < 0 ) {
|
||||
d += bits_per_block;
|
||||
--m_block_iterator;
|
||||
}
|
||||
m_bit_index = static_cast< int >( d );
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator==( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return lhs.m_block_iterator == rhs.m_block_iterator && lhs.m_bit_index == rhs.m_bit_index;
|
||||
}
|
||||
|
||||
#if __cpp_lib_three_way_comparison
|
||||
template< typename Iterator >
|
||||
std::strong_ordering
|
||||
operator<=>( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
if ( const auto cmp = lhs.m_block_iterator <=> rhs.m_block_iterator; cmp != 0 ) {
|
||||
return cmp;
|
||||
} else {
|
||||
return lhs.m_bit_index <=> rhs.m_bit_index;
|
||||
}
|
||||
}
|
||||
#else
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator!=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return !( lhs == rhs );
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator<( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return lhs.m_block_iterator < rhs.m_block_iterator
|
||||
|| ( lhs.m_block_iterator == rhs.m_block_iterator && lhs.m_bit_index < rhs.m_bit_index );
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator<=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return !( rhs < lhs );
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator>( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template< typename Iterator >
|
||||
bool
|
||||
operator>=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return !( lhs < rhs );
|
||||
}
|
||||
#endif // __cpp_lib_three_way_comparison
|
||||
|
||||
template< typename Iterator >
|
||||
std::ptrdiff_t
|
||||
operator-( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
|
||||
{
|
||||
return ( lhs.m_block_iterator - rhs.m_block_iterator ) * bit_iterator_base< Iterator >::bits_per_block
|
||||
+ lhs.m_bit_index - rhs.m_bit_index;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset>
|
||||
bit_iterator< DynamicBitset >::bit_iterator()
|
||||
: bit_iterator_base< typename DynamicBitset::buffer_type::iterator >()
|
||||
{
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >::bit_iterator( typename DynamicBitset::buffer_type::iterator block_iterator, int bit_index )
|
||||
: bit_iterator_base< typename DynamicBitset::buffer_type::iterator >( block_iterator, bit_index )
|
||||
{
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
typename DynamicBitset::reference
|
||||
bit_iterator< DynamicBitset >::operator*() const
|
||||
{
|
||||
return reference( *(this->m_block_iterator), this->m_bit_index );
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset > &
|
||||
bit_iterator< DynamicBitset >::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >
|
||||
bit_iterator< DynamicBitset >::operator++( int )
|
||||
{
|
||||
bit_iterator temp = *this;
|
||||
this->increment();
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset > &
|
||||
bit_iterator< DynamicBitset >::operator--()
|
||||
{
|
||||
this->decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >
|
||||
bit_iterator< DynamicBitset >::operator--( int )
|
||||
{
|
||||
bit_iterator temp = *this;
|
||||
this->decrement();
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset > &
|
||||
bit_iterator< DynamicBitset >::operator+=( difference_type n )
|
||||
{
|
||||
this->add( n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset > &
|
||||
bit_iterator< DynamicBitset >::operator-=( difference_type n )
|
||||
{
|
||||
this->add( -n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >
|
||||
operator+( const bit_iterator< DynamicBitset > & it, typename bit_iterator< DynamicBitset >::difference_type n )
|
||||
{
|
||||
bit_iterator< DynamicBitset > temp = it;
|
||||
temp += n;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >
|
||||
operator+( typename bit_iterator< DynamicBitset >::difference_type n, const bit_iterator< DynamicBitset > & it )
|
||||
{
|
||||
return it + n;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
bit_iterator< DynamicBitset >
|
||||
operator-( const bit_iterator< DynamicBitset > & it, typename bit_iterator< DynamicBitset >::difference_type n )
|
||||
{
|
||||
bit_iterator< DynamicBitset > temp = it;
|
||||
temp -= n;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
typename DynamicBitset::reference
|
||||
bit_iterator< DynamicBitset >::operator[]( difference_type n ) const
|
||||
{
|
||||
return *( *this + n );
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >::const_bit_iterator( typename DynamicBitset::buffer_type::const_iterator block_iterator, int bit_index )
|
||||
: bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >( block_iterator, bit_index )
|
||||
{
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >::const_bit_iterator( const bit_iterator< DynamicBitset > & it )
|
||||
: bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >( it.m_block_iterator, it.m_bit_index )
|
||||
{
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
typename const_bit_iterator< DynamicBitset >::const_reference
|
||||
const_bit_iterator< DynamicBitset >::operator*() const
|
||||
{
|
||||
return ( *( this->m_block_iterator ) & ( typename DynamicBitset::block_type( 1 ) << this->m_bit_index ) ) != 0;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset > &
|
||||
const_bit_iterator< DynamicBitset >::const_bit_iterator::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >::operator++( int )
|
||||
{
|
||||
const_bit_iterator temp = *this;
|
||||
this->increment();
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset > &
|
||||
const_bit_iterator< DynamicBitset >::const_bit_iterator::operator--()
|
||||
{
|
||||
this->decrement();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >::operator--( int )
|
||||
{
|
||||
const_bit_iterator temp = *this;
|
||||
this->decrement();
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset > &
|
||||
const_bit_iterator< DynamicBitset >::operator+=( difference_type n )
|
||||
{
|
||||
this->add( n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset > &
|
||||
const_bit_iterator< DynamicBitset >::operator-=( difference_type n )
|
||||
{
|
||||
this->add( -n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >
|
||||
operator+( const const_bit_iterator< DynamicBitset > & it,
|
||||
typename const_bit_iterator< DynamicBitset >::difference_type n )
|
||||
{
|
||||
const_bit_iterator< DynamicBitset > temp = it;
|
||||
temp += n;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >
|
||||
operator+( typename const_bit_iterator< DynamicBitset >::difference_type n,
|
||||
const const_bit_iterator< DynamicBitset > & it )
|
||||
{
|
||||
return it + n;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
const_bit_iterator< DynamicBitset >
|
||||
operator-( const const_bit_iterator< DynamicBitset > & it,
|
||||
typename const_bit_iterator< DynamicBitset >::difference_type n )
|
||||
{
|
||||
const_bit_iterator< DynamicBitset > temp = it;
|
||||
temp -= n;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template< typename DynamicBitset >
|
||||
typename const_bit_iterator< DynamicBitset >::const_reference
|
||||
const_bit_iterator< DynamicBitset >::operator[]( difference_type n ) const
|
||||
{
|
||||
return *( *this + n );
|
||||
}
|
||||
|
||||
|
||||
template< typename BlockIterator, typename B, typename A >
|
||||
void
|
||||
from_block_range( BlockIterator first, BlockIterator last, dynamic_bitset< B, A > & result )
|
||||
@@ -228,6 +541,98 @@ dynamic_bitset< Block, AllocatorOrContainer >::~dynamic_bitset()
|
||||
BOOST_ASSERT( m_check_invariants() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::begin()
|
||||
{
|
||||
return iterator( m_bits.begin(), 0 );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::begin() const
|
||||
{
|
||||
return const_iterator( m_bits.cbegin(), 0 );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::end()
|
||||
{
|
||||
if ( count_extra_bits() == 0 ) {
|
||||
return iterator( m_bits.end(), 0 );
|
||||
} else {
|
||||
return iterator( std::prev( m_bits.end() ), size() % bits_per_block );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::end() const
|
||||
{
|
||||
if ( count_extra_bits() == 0 ) {
|
||||
return const_iterator( m_bits.cend(), 0 );
|
||||
} else {
|
||||
return const_iterator( std::prev( m_bits.cend() ), size() % bits_per_block );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::rbegin()
|
||||
{
|
||||
return reverse_iterator( end() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::rbegin() const
|
||||
{
|
||||
return const_reverse_iterator( end() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::rend()
|
||||
{
|
||||
return reverse_iterator( begin() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::rend() const
|
||||
{
|
||||
return const_reverse_iterator( begin() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::cbegin() const
|
||||
{
|
||||
return const_iterator( begin() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::cend() const
|
||||
{
|
||||
return const_iterator( end() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::crbegin() const
|
||||
{
|
||||
return const_reverse_iterator( end() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::crend() const
|
||||
{
|
||||
return const_reverse_iterator( begin() );
|
||||
}
|
||||
|
||||
template< typename Block, typename AllocatorOrContainer >
|
||||
void
|
||||
dynamic_bitset< Block, AllocatorOrContainer >::
|
||||
|
||||
@@ -210,6 +210,51 @@ struct bitset_test
|
||||
BOOST_TEST( b[ j ] == 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
iterate_forward( const Bitset & b )
|
||||
{
|
||||
std::ptrdiff_t i = 0;
|
||||
for ( auto it = b.begin(); it != b.end(); ++it ) {
|
||||
BOOST_TEST( *it == b[ i ] );
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iterate_backward( const Bitset & b )
|
||||
{
|
||||
std::ptrdiff_t i = static_cast< std::ptrdiff_t >( b.size() ) - 1;
|
||||
for ( auto it = b.rbegin(); it != b.rend(); ++it ) {
|
||||
BOOST_TEST( *it == b[ i ] );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iterator_operations( const Bitset & b )
|
||||
{
|
||||
if ( b.size() >= 1 ) {
|
||||
BOOST_TEST( *( b.end() - 1 ) == b[ b.size() - 1 ] );
|
||||
BOOST_TEST( b.begin() < b.end() );
|
||||
BOOST_TEST( b.begin() <= b.end() );
|
||||
BOOST_TEST( b.end() > b.begin() );
|
||||
BOOST_TEST( b.end() >= b.begin() );
|
||||
typename Bitset::const_iterator it = b.begin();
|
||||
it += b.size() / 2;
|
||||
BOOST_TEST( *it == b[ b.size() / 2 ] );
|
||||
it -= b.size() / 2;
|
||||
BOOST_TEST( *it == b[ 0 ] );
|
||||
} else {
|
||||
BOOST_TEST( b.begin() == b.end() );
|
||||
}
|
||||
|
||||
if ( b.size() > 1 ) {
|
||||
BOOST_TEST( *( b.begin() + 1 ) == b[ 1 ] );
|
||||
BOOST_TEST( *( 1 + b.begin() ) == b[ 1 ] );
|
||||
BOOST_TEST( *( b.end() - 1 ) == b[ b.size() - 1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
to_block_range( const Bitset & b /*, BlockOutputIterator result*/ )
|
||||
{
|
||||
|
||||
@@ -233,6 +233,34 @@ run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE( Block ) )
|
||||
blocks[ i ] = static_cast< Block >( i );
|
||||
Tests::from_block_range( blocks );
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// test iterators
|
||||
{
|
||||
bitset_type b;
|
||||
Tests::iterate_forward( b );
|
||||
Tests::iterate_backward( b );
|
||||
Tests::iterator_operations( b );
|
||||
}
|
||||
{
|
||||
bitset_type b( 1, 1ul );
|
||||
Tests::iterate_forward( b );
|
||||
Tests::iterate_backward( b );
|
||||
Tests::iterator_operations( b );
|
||||
}
|
||||
{
|
||||
bitset_type b( bitset_type::bits_per_block, 100ul );
|
||||
Tests::iterate_forward( b );
|
||||
Tests::iterate_backward( b );
|
||||
Tests::iterator_operations( b );
|
||||
}
|
||||
{
|
||||
bitset_type b( long_string );
|
||||
Tests::iterate_forward( b );
|
||||
Tests::iterate_backward( b );
|
||||
Tests::iterator_operations( b );
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// test to_block_range
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user