From 35b00945295ecfe425cbc85bda92180e3d6d023e Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Tue, 9 Sep 2025 14:42:38 +0200 Subject: [PATCH] Add C++20 iterators Reason: Requested on the mailing list. --- doc/modules/ROOT/pages/index.adoc | 20 +- .../boost/dynamic_bitset/dynamic_bitset.hpp | 163 ++++++- .../dynamic_bitset/impl/dynamic_bitset.ipp | 405 ++++++++++++++++++ test/bitset_test.hpp | 45 ++ test/dyn_bitset_unit_tests1.cpp | 28 ++ 5 files changed, 645 insertions(+), 16 deletions(-) diff --git a/doc/modules/ROOT/pages/index.adoc b/doc/modules/ROOT/pages/index.adoc index a6773fc..84f5ec4 100644 --- a/doc/modules/ROOT/pages/index.adoc +++ b/doc/modules/ROOT/pages/index.adoc @@ -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 Container -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` 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` with -a standard algorithm such as `std::search()`. The `std::search()` requirements -say that the iterator must be a LegacyForwardIterator, but -`std::vector::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 diff --git a/include/boost/dynamic_bitset/dynamic_bitset.hpp b/include/boost/dynamic_bitset/dynamic_bitset.hpp index 7500314..d8b404a 100644 --- a/include/boost/dynamic_bitset/dynamic_bitset.hpp +++ b/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -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 +#endif #include #include #include @@ -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 //! allocator -//! 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. diff --git a/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp b/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp index a1f5725..c027a03 100644 --- a/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp +++ b/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp @@ -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 >:: diff --git a/test/bitset_test.hpp b/test/bitset_test.hpp index 40684b1..1dca01d 100644 --- a/test/bitset_test.hpp +++ b/test/bitset_test.hpp @@ -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*/ ) { diff --git a/test/dyn_bitset_unit_tests1.cpp b/test/dyn_bitset_unit_tests1.cpp index b7b6f0f..b3bb27d 100644 --- a/test/dyn_bitset_unit_tests1.cpp +++ b/test/dyn_bitset_unit_tests1.cpp @@ -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 {