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.)
This commit is contained in:
Gennaro Prota
2025-09-11 15:30:22 +02:00
parent 079cff781d
commit 0177f4adfa
3 changed files with 74 additions and 42 deletions

View File

@@ -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<CharT, Traits, Alloc>::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*/

View File

@@ -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' ) ) );
}
}
}

View File

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