From 98ed4a79e930ae0ce3972b9277c4545704bbad82 Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Fri, 2 Oct 2026 09:27:12 -0700 Subject: [PATCH] Fix empty string-view construction and assignment --- include/boost/container/string.hpp | 11 +++++-- test/string_view_compat_test.cpp | 47 +++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 5793acfe..b29ba965 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -838,7 +838,7 @@ class basic_string : base_t() { this->priv_terminate_string(); - this->assign(s, n); // assign checks for s != 0 + this->assign(s, n); // assign checks for s != 0 when n != 0 } //! Effects: Constructs a basic_string taking the allocator as parameter, @@ -847,7 +847,7 @@ class basic_string : base_t(a) { this->priv_terminate_string(); - this->assign(s, n); // assign checks for s != 0 + this->assign(s, n); // assign checks for s != 0 when n != 0 } //! Effects: Constructs a basic_string with a default-constructed allocator, @@ -1652,6 +1652,7 @@ class basic_string } //! Requires: s points to an array of at least n elements of CharT. + //! If n is zero, s may be null. //! //! Effects: Replaces the string controlled by *this with a string of //! length n whose elements are a copy of those pointed to by s. @@ -1661,7 +1662,11 @@ class basic_string //! Returns: *this basic_string& assign(const CharT* s, size_type n) { - BOOST_ASSERT(s != 0); + BOOST_ASSERT(s != 0 || n == 0); + if(n == 0){ + this->clear(); + return *this; + } return this->assign(s, s + difference_type(n)); } diff --git a/test/string_view_compat_test.cpp b/test/string_view_compat_test.cpp index 31b2acf8..d0ca2944 100644 --- a/test/string_view_compat_test.cpp +++ b/test/string_view_compat_test.cpp @@ -172,6 +172,49 @@ void assign_test() BOOST_TEST(sv == s); } +template +void empty_assign_test() +{ + typedef typename StringViewType::value_type char_type; + typedef boost::container::basic_string string_type; + const char_type empty[] = { char_type(0) }; + const char_type value = char_type('y'); + const StringViewType views[] = { StringViewType(), StringViewType(empty) }; + const std::size_t sizes[] = { 0u, 7u, 128u }; + for(std::size_t i = 0; i != sizeof(views)/sizeof(views[0]); ++i){ + const StringViewType sv = views[i]; + string_type constructed(sv); + BOOST_TEST(constructed.empty()); + BOOST_TEST(constructed.c_str()[0] == char_type(0)); + string_type constructed_with_allocator(sv, constructed.get_allocator()); + BOOST_TEST(constructed_with_allocator.empty()); + BOOST_TEST(constructed_with_allocator.c_str()[0] == char_type(0)); + + for(std::size_t j = 0; j != sizeof(sizes)/sizeof(sizes[0]); ++j){ + string_type s(sizes[j], char_type('x')); + const std::size_t capacity = s.capacity(); + BOOST_TEST(&s.assign(sv) == &s); + BOOST_TEST(s.empty()); + BOOST_TEST(s.c_str()[0] == char_type(0)); + BOOST_TEST(s.capacity() == capacity); + + s.assign(sizes[j], char_type('x')); + BOOST_TEST(&(s = sv) == &s); + BOOST_TEST(s.empty()); + BOOST_TEST(s.c_str()[0] == char_type(0)); + + s.assign(sizes[j], char_type('x')); + BOOST_TEST(&s.assign(sv.data(), sv.size()) == &s); + BOOST_TEST(s.empty()); + BOOST_TEST(s.c_str()[0] == char_type(0)); + + s.assign(StringViewType(&value, 1u)); + BOOST_TEST(s.size() == 1u); + BOOST_TEST(s[0] == value); + } + } +} + template void plus_equal_test() { @@ -310,6 +353,7 @@ void test_all() constructor_test(); assignment_test(); assign_test(); + empty_assign_test(); plus_equal_test(); append_test(); insert_test(); @@ -327,10 +371,11 @@ void test_all() int main() { test_all(); + empty_assign_test(); #ifdef BOOST_CONTAINER_TEST_HAS_STD_STRING_VIEW test_all(); + empty_assign_test(); #endif return boost::report_errors(); } -