From 0177f4adfa809b80ba6eee759a8f0c1bed5671eb Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Thu, 11 Sep 2025 15:30:22 +0200 Subject: [PATCH] Add a constructor from const CharT * (pointer to C-style string) This is in preparation of the next commit, which will add a constructor from std::basic_string_view (otherwise, construction from a C-style string would be ambiguous between the basic_string_view and the basic_string constructor). Note that, rather than duplicating code to test the new member, we changed many constructions in dyn_bitset_unit_tests1.cpp to use const char *, instead of std::string. (The constructor from std::basic_string is tested separately anyway.) --- .../boost/dynamic_bitset/dynamic_bitset.hpp | 25 +++++++++- .../dynamic_bitset/impl/dynamic_bitset.ipp | 41 +++++++++------ test/dyn_bitset_unit_tests1.cpp | 50 +++++++++---------- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/include/boost/dynamic_bitset/dynamic_bitset.hpp b/include/boost/dynamic_bitset/dynamic_bitset.hpp index 42cf459..799eed4 100644 --- a/include/boost/dynamic_bitset/dynamic_bitset.hpp +++ b/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -365,6 +365,27 @@ public: template< typename CharT, typename Traits, typename Alloc > dynamic_bitset( const std::basic_string< CharT, Traits, Alloc > & s, typename std::basic_string< CharT, Traits, Alloc >::size_type pos = 0, typename std::basic_string< CharT, Traits, Alloc >::size_type n = (std::basic_string::npos), size_type num_bits = npos, const allocator_type & alloc = allocator_type() ); + //! Similar to the constructor from a `basic_string`, but takes + //! a pointer to a C-style string (and doesn't take a `pos`). + //! + //! The size of the bitset is `num_bits` if `num_bits != npos`, + //! otherwise `rlen = min( n, std::char_traits< CharT >::length( s ) )`. + //! The first `M = min( num_bits, rlen )` bits are initialized + //! to the corresponding characters in `s`. + //! + //! \pre + //! The characters in `s` are '0' or '1'. + //! + //! \param s The string to construct from. + //! \param n The maximum number of characters in the string to + //! consider. + //! \param num_bits The size of the bitset to construct, if + //! different from `npos`. + //! \param alloc The allocator to use. + // ----------------------------------------------------------------------- + template< typename CharT > + dynamic_bitset( const CharT * s, std::size_t n = std::size_t( -1 ), size_type num_bits = npos, const allocator_type & alloc = allocator_type() ); + //! Constructs a bitset from a range of blocks or from an //! integer. //! @@ -1286,8 +1307,8 @@ private: template< typename BlockIter > void init_from_block_range( BlockIter first, BlockIter last ); - template< typename CharT, typename Traits, typename Alloc > - void init_from_string( const std::basic_string< CharT, Traits, Alloc > & s, typename std::basic_string< CharT, Traits, Alloc >::size_type pos, typename std::basic_string< CharT, Traits, Alloc >::size_type n, size_type num_bits ); + template< typename CharT, typename Traits = std::char_traits< CharT > > + void init_from_string( const CharT * s, std::size_t pos, std::size_t n, size_type num_bits ); void init_from_unsigned_long( size_type num_bits, unsigned long value /*, const allocator_type& alloc*/ diff --git a/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp b/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp index acb1d04..c1f11a9 100644 --- a/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp +++ b/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp @@ -494,9 +494,22 @@ dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( : m_bits( alloc ), m_num_bits( 0 ) { - init_from_string( s, pos, n, num_bits ); + init_from_string( s.c_str(), pos, n, num_bits ); } +template< typename Block, typename AllocatorOrContainer > +template< typename CharT > +dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( + const CharT * s, + std::size_t n, + size_type num_bits, + const allocator_type & alloc ) + : m_bits( alloc ), m_num_bits( 0 ) +{ + init_from_string( s, 0, n, num_bits ); +} + + template< typename Block, typename AllocatorOrContainer > template< typename BlockInputIterator > dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( @@ -2045,21 +2058,20 @@ dynamic_bitset< Block, AllocatorOrContainer >::init_from_block_range( BlockIter } template< typename Block, typename AllocatorOrContainer > -template< typename CharT, typename Traits, typename Alloc > +template< typename CharT, typename Traits > void dynamic_bitset< Block, AllocatorOrContainer >::init_from_string( - const std::basic_string< CharT, Traits, Alloc > & s, - typename std::basic_string< CharT, Traits, Alloc >::size_type pos, - typename std::basic_string< CharT, Traits, Alloc >::size_type n, - size_type num_bits ) + const CharT * s, + std::size_t pos, + std::size_t n, + size_type num_bits ) { - BOOST_ASSERT( pos <= s.size() ); + const std::size_t string_length = Traits::length( s ); + BOOST_ASSERT( pos <= string_length ); - typedef typename std::basic_string< CharT, Traits, Alloc > StrT; - typedef typename StrT::traits_type Tr; - const typename StrT::size_type rlen = (std::min)( n, s.size() - pos ); - const size_type sz = ( num_bits != npos ? num_bits : rlen ); + const std::size_t rlen = (std::min)( n, string_length - pos ); + const size_type sz = ( num_bits != npos ? num_bits : rlen ); m_bits.resize( calc_num_blocks( sz ) ); m_num_bits = sz; @@ -2067,14 +2079,13 @@ dynamic_bitset< Block, AllocatorOrContainer >::init_from_string( const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR( fac, '1' ); const size_type m = num_bits < rlen ? num_bits : rlen; - typename StrT::size_type i = 0; - for ( ; i < m; ++i ) { + for ( std::size_t i = 0; i < m; ++i ) { const CharT c = s[ ( pos + m - 1 ) - i ]; - if ( Tr::eq( c, one ) ) { + if ( Traits::eq( c, one ) ) { set( i ); } else { - BOOST_ASSERT( Tr::eq( c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR( fac, '0' ) ) ); + BOOST_ASSERT( Traits::eq( c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR( fac, '0' ) ) ); } } } diff --git a/test/dyn_bitset_unit_tests1.cpp b/test/dyn_bitset_unit_tests1.cpp index 72e76fd..313f72d 100644 --- a/test/dyn_bitset_unit_tests1.cpp +++ b/test/dyn_bitset_unit_tests1.cpp @@ -275,7 +275,7 @@ run_test_cases() Tests::copy_constructor( b ); } { - bitset_type b( std::string( "0" ) ); + bitset_type b( "0" ); Tests::copy_constructor( b ); } { @@ -289,7 +289,7 @@ run_test_cases() Tests::copy_assignment_operator( a, b ); } { - bitset_type a( std::string( "1" ) ), b( std::string( "0" ) ); + bitset_type a( "1" ), b( "0" ); Tests::copy_assignment_operator( a, b ); } { @@ -302,7 +302,7 @@ run_test_cases() Tests::copy_assignment_operator( a, b ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); bitset_type b( long_string ); // b greater than a Tests::copy_assignment_operator( a, b ); } @@ -315,7 +315,7 @@ run_test_cases() Tests::move_constructor( b ); } { - bitset_type b( std::string( "0" ) ); + bitset_type b( "0" ); Tests::move_constructor( b ); } { @@ -329,7 +329,7 @@ run_test_cases() Tests::move_assignment_operator( a, b ); } { - bitset_type a( std::string( "1" ) ), b( std::string( "0" ) ); + bitset_type a( "1" ), b( "0" ); Tests::move_assignment_operator( a, b ); } { @@ -342,7 +342,7 @@ run_test_cases() Tests::move_assignment_operator( a, b ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); bitset_type b( long_string ); // b greater than a Tests::move_assignment_operator( a, b ); } @@ -351,7 +351,7 @@ run_test_cases() // Test swap { bitset_type a; - bitset_type b( std::string( "1" ) ); + bitset_type b( "1" ); Tests::swap( a, b ); Tests::swap( b, a ); Tests::swap( a, a ); @@ -363,7 +363,7 @@ run_test_cases() Tests::swap( b, a ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); bitset_type b( long_string ); Tests::swap( a, b ); Tests::swap( b, a ); @@ -377,11 +377,11 @@ run_test_cases() Tests::resize( a ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); Tests::resize( a ); } { - bitset_type a( std::string( "1" ) ); + bitset_type a( "1" ); Tests::resize( a ); } { @@ -401,11 +401,11 @@ run_test_cases() //===================================================================== // Test pop back { - bitset_type a( std::string( "01" ) ); + bitset_type a( "01" ); Tests::pop_back( a ); } { - bitset_type a( std::string( "10" ) ); + bitset_type a( "10" ); Tests::pop_back( a ); } { @@ -414,7 +414,7 @@ run_test_cases() Tests::pop_back( a ); } { - bitset_type a( long_string ); + bitset_type a( long_string.c_str() ); Tests::pop_back( a ); } //===================================================================== @@ -424,11 +424,11 @@ run_test_cases() Tests::append_bit( a ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); Tests::append_bit( a ); } { - bitset_type a( std::string( "1" ) ); + bitset_type a( "1" ); Tests::append_bit( a ); } { @@ -447,11 +447,11 @@ run_test_cases() Tests::append_block( a ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); Tests::append_block( a ); } { - bitset_type a( std::string( "1" ) ); + bitset_type a( "1" ); Tests::append_block( a ); } { @@ -460,7 +460,7 @@ run_test_cases() Tests::append_block( a ); } { - bitset_type a( long_string ); + bitset_type a( long_string.c_str() ); Tests::append_block( a ); } //===================================================================== @@ -471,7 +471,7 @@ run_test_cases() Tests::append_block_range( a, blocks ); } { - bitset_type a( std::string( "0" ) ); + bitset_type a( "0" ); std::vector< Block > blocks( 3 ); blocks[ 0 ] = static_cast< Block >( 0 ); blocks[ 1 ] = static_cast< Block >( 1 ); @@ -479,7 +479,7 @@ run_test_cases() Tests::append_block_range( a, blocks ); } { - bitset_type a( std::string( "1" ) ); + bitset_type a( "1" ); const unsigned int n = ( std::numeric_limits< unsigned char >::max )(); std::vector< Block > blocks( n ); for ( typename std::vector< Block >::size_type i = 0; i < n; ++i ) @@ -496,7 +496,7 @@ run_test_cases() Tests::append_block_range( a, blocks ); } { - bitset_type a( long_string ); + bitset_type a( long_string.c_str() ); std::vector< Block > blocks( 3 ); blocks[ 0 ] = static_cast< Block >( 0 ); blocks[ 1 ] = static_cast< Block >( 1 ); @@ -511,12 +511,12 @@ run_test_cases() Tests::operator_bracket( b1, bitvec1 ); } { - bitset_type b( std::string( "1" ) ); + bitset_type b( "1" ); std::vector< bool > bit_vec( 1, true ); Tests::operator_bracket( b, bit_vec ); } { - bitset_type b( long_string ); + bitset_type b( long_string.c_str() ); std::size_t n = long_string.size(); std::vector< bool > bit_vec( n ); for ( std::size_t i = 0; i < n; ++i ) @@ -531,12 +531,12 @@ run_test_cases() Tests::at( b1, bitvec1 ); } { - bitset_type b( std::string( "1" ) ); + bitset_type b( "1" ); std::vector< bool > bit_vec( 1, true ); Tests::at( b, bit_vec ); } { - bitset_type b( long_string ); + bitset_type b( long_string.c_str() ); std::size_t n = long_string.size(); std::vector< bool > bit_vec( n ); for ( std::size_t i = 0; i < n; ++i )