From bb489c186afffc5a291ad80a40d1906d567025f1 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Thu, 11 Sep 2025 16:49:26 +0200 Subject: [PATCH] Add a constructor from basic_string_view in C++17 or later Note that we have MrDocs compile as C++17 again (a change that we had reverted). --- CMakeLists.txt | 3 +++ include/boost/dynamic_bitset/config.hpp | 4 ++++ .../boost/dynamic_bitset/dynamic_bitset.hpp | 23 ++++++++++++++++++- .../dynamic_bitset/impl/dynamic_bitset.ipp | 22 ++++++++++++++---- test/bitset_test.hpp | 4 ++++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0da5814..86e4ca2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,9 @@ if (DYNAMIC_BITSET_MRDOCS_BUILD) # Create a custom target for MrDocs. add_library(dynamic_bitset_mrdocs_target ${TEMP_CPP_FILE}) + # This is to get the documentation of the constructor from basic_string_view. + set_target_properties(dynamic_bitset_mrdocs_target PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES) + # Set any other target properties here. target_include_directories(dynamic_bitset_mrdocs_target PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(dynamic_bitset_mrdocs_target PRIVATE boost_dynamic_bitset) diff --git a/include/boost/dynamic_bitset/config.hpp b/include/boost/dynamic_bitset/config.hpp index bc98ecd..4598c86 100644 --- a/include/boost/dynamic_bitset/config.hpp +++ b/include/boost/dynamic_bitset/config.hpp @@ -60,4 +60,8 @@ make_non_const( T t ) # define BOOST_DYNAMIC_BITSET_SPECIALIZE_STD_HASH #endif +#if ( defined( _MSVC_LANG ) && _MSVC_LANG >= 201703L ) || __cplusplus >= 201703L +# define BOOST_DYNAMIC_BITSET_USE_CPP17_OR_LATER +#endif + #endif // include guard diff --git a/include/boost/dynamic_bitset/dynamic_bitset.hpp b/include/boost/dynamic_bitset/dynamic_bitset.hpp index 799eed4..cf70082 100644 --- a/include/boost/dynamic_bitset/dynamic_bitset.hpp +++ b/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -386,6 +386,27 @@ public: 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() ); +#if defined( BOOST_DYNAMIC_BITSET_USE_CPP17_OR_LATER ) + + //! Similar to the constructor from a pointer to a C-style + //! string, but takes a `std::basic_string_view`. This + //! constructor is only available if DynamicBitset is compiled + //! as C++17 or later. + //! + //! \pre + //! The characters in `sv` are '0' or '1'. + //! + //! \param sv The basic_string_view to construct from. + //! \param num_bits The size of the bitset to construct, if + //! different from `npos`. (Otherwise the size of the bitset is + //! `sv.length()`.) + //! \param alloc The allocator to use. + // ----------------------------------------------------------------------- + template< typename CharT, typename Traits > + dynamic_bitset( std::basic_string_view< CharT, Traits > sv, size_type num_bits = npos, const allocator_type & alloc = allocator_type() ); + +#endif + //! Constructs a bitset from a range of blocks or from an //! integer. //! @@ -1308,7 +1329,7 @@ private: void init_from_block_range( BlockIter first, BlockIter last ); 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_string( const CharT * s, std::size_t string_length, 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 c1f11a9..8bd16b1 100644 --- a/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp +++ b/include/boost/dynamic_bitset/impl/dynamic_bitset.ipp @@ -494,7 +494,7 @@ dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( : m_bits( alloc ), m_num_bits( 0 ) { - init_from_string( s.c_str(), pos, n, num_bits ); + init_from_string( s.c_str(), s.length(), pos, n, num_bits ); } template< typename Block, typename AllocatorOrContainer > @@ -506,9 +506,23 @@ dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( const allocator_type & alloc ) : m_bits( alloc ), m_num_bits( 0 ) { - init_from_string( s, 0, n, num_bits ); + init_from_string( s, std::char_traits< CharT >::length( s ), 0, n, num_bits ); } +#if defined( BOOST_DYNAMIC_BITSET_USE_CPP17_OR_LATER ) + +template< typename Block, typename AllocatorOrContainer > +template< typename CharT, typename Traits > +dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( + std::basic_string_view< CharT, Traits > sv, + size_type num_bits, + const allocator_type & alloc ) + : m_bits( alloc ), m_num_bits( 0 ) +{ + init_from_string( sv.data(), sv.length(), 0, sv.length(), num_bits ); +} + +#endif template< typename Block, typename AllocatorOrContainer > template< typename BlockInputIterator > @@ -2061,12 +2075,12 @@ template< typename Block, typename AllocatorOrContainer > template< typename CharT, typename Traits > void dynamic_bitset< Block, AllocatorOrContainer >::init_from_string( - const CharT * s, + const CharT * s, // caution: not necessarily null-terminated + std::size_t string_length, std::size_t pos, std::size_t n, size_type num_bits ) { - const std::size_t string_length = Traits::length( s ); BOOST_ASSERT( pos <= string_length ); diff --git a/test/bitset_test.hpp b/test/bitset_test.hpp index 7518b97..307e52b 100644 --- a/test/bitset_test.hpp +++ b/test/bitset_test.hpp @@ -208,6 +208,10 @@ struct bitset_test // If M < N, remaining bit positions are zero for ( ; j < actual_size; ++j ) BOOST_TEST( b[ j ] == 0 ); + +#if defined( BOOST_DYNAMIC_BITSET_USE_CPP17_OR_LATER ) + BOOST_TEST( Bitset( std::basic_string_view< Ch, Tr >( str ).substr( pos, rlen ), num_bits ) == b ); +#endif } static void