diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp
index fb4dd9e..fce660d 100644
--- a/include/boost/container/string.hpp
+++ b/include/boost/container/string.hpp
@@ -1437,6 +1437,23 @@ class basic_string
s.begin() + pos + dtl::min_value(n, s.size() - pos));
}
+ //! Requires: pos <= sv.size()
+ //!
+ //! Effects: Determines the effective length rlen of the string to append
+ //! as the smaller of n and sv.size() - pos and calls append(sv.data() + pos, rlen).
+ //!
+ //! Throws: If memory allocation throws and out_of_range if pos > sv.size()
+ //!
+ //! Returns: *this
+ template class BasicStringView>
+ basic_string& append(BasicStringView sv, size_type pos, size_type n = npos)
+ {
+ if (pos > sv.size())
+ throw_out_of_range("basic_string::append out of range position");
+ return this->append(sv.begin() + pos,
+ sv.begin() + pos + dtl::min_value(n, sv.size() - pos));
+ }
+
//! Requires: s points to an array of at least n elements of CharT.
//!
//! Effects: The function replaces the string controlled by *this with
@@ -1499,12 +1516,18 @@ class basic_string
}
}
- //! Effects: Equivalent to assign(str, 0, npos).
+ //! Effects: return *this = s;
//!
//! Returns: *this
basic_string& assign(const basic_string& s)
{ return this->operator=(s); }
+ //! Effects: return *this = move(s);
+ //!
+ //! Returns: *this
+ basic_string& assign(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->operator=(boost::move(s)); }
+
//! Effects: Equivalent to return assign(sv.data(), sv.size()).
//!
//! Returns: *this
@@ -1512,15 +1535,22 @@ class basic_string
basic_string& assign(BasicStringView sv)
{ return this->operator=(sv); }
- //! Effects: The function replaces the string controlled by *this
- //! with a string of length str.size() whose elements are a copy of the string
- //! controlled by str. Leaves str in a valid but unspecified state.
+ //! Requires: pos <= sv.size()
//!
- //! Throws: Nothing
+ //! Effects: Determines the effective length rlen of the string to assign as
+ //! the smaller of n and sv.size() - pos and calls assign(sv.data() + pos rlen).
+ //!
+ //! Throws: If memory allocation throws or out_of_range if pos > sv.size().
//!
//! Returns: *this
- basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
- { return this->swap_data(ms), *this; }
+ template class BasicStringView>
+ basic_string& assign(BasicStringView sv, size_type pos, size_type n = npos)
+ {
+ if (pos > sv.size())
+ throw_out_of_range("basic_string::assign out of range position");
+ return this->assign(sv.begin() + pos,
+ sv.begin() + pos + dtl::min_value(n, sv.size() - pos));
+ }
//! Requires: pos <= str.size()
//!
@@ -1716,6 +1746,31 @@ class basic_string
basic_string& insert(size_type pos, BasicStringView sv)
{ return this->insert(pos, sv.data(), sv.size()); }
+
+ //! Requires: pos1 <= size() and pos2 <= sv.size()
+ //!
+ //! Effects: Determines the effective length rlen of the string to insert as
+ //! the smaller of n and sv.size() - pos2 and calls insert(pos1, sv.data() + pos2, rlen).
+ //!
+ //! Throws: If memory allocation throws or out_of_range if pos1 > size() or pos2 > sv.size().
+ //!
+ //! Returns: *this
+ template class BasicStringView>
+ basic_string& insert(size_type pos1, BasicStringView sv, size_type pos2, size_type n = npos)
+ {
+ const size_type sz = this->size();
+ const size_type str_size = sv.size();
+ if (pos1 > sz || pos2 > str_size)
+ throw_out_of_range("basic_string::insert out of range position");
+ size_type len = dtl::min_value(n, str_size - pos2);
+ if (sz > this->max_size() - len)
+ throw_length_error("basic_string::insert max_size() exceeded");
+ const CharT *beg_ptr = boost::movelib::to_raw_pointer(sv.begin()) + pos2;
+ const CharT *end_ptr = beg_ptr + len;
+ this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
+ return *this;
+ }
+
//! Requires: p is a valid iterator on *this.
//!
//! Effects: inserts a copy of c before the character referred to by p.
diff --git a/test/string_test.cpp b/test/string_test.cpp
index b9674df..aab577e 100644
--- a/test/string_test.cpp
+++ b/test/string_test.cpp
@@ -520,8 +520,1906 @@ struct alloc_propagate_base
}}} //namespace boost::container::test
+/*
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Namespace alias for convenience
+namespace bc = boost::container;
+
+// Helper to suppress unused variable warnings
+template
+void use(T const&) {}
+
+//==============================================================================
+// SECTION 1: Type traits and typedefs
+//==============================================================================
+
+void test_type_traits()
+{
+ // Basic type traits
+ BOOST_TEST_TRAIT_TRUE((std::is_same));
+ BOOST_TEST_TRAIT_TRUE((std::is_same>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same));
+ BOOST_TEST_TRAIT_TRUE((std::is_same));
+ BOOST_TEST_TRAIT_TRUE((std::is_same));
+ BOOST_TEST_TRAIT_TRUE((std::is_same));
+
+ // Iterator types should be random access
+ using iter = bc::string::iterator;
+ using citer = bc::string::const_iterator;
+ using riter = bc::string::reverse_iterator;
+ using criter = bc::string::const_reverse_iterator;
+
+ BOOST_TEST_TRAIT_TRUE((std::is_same<
+ typename std::iterator_traits::iterator_category,
+ std::random_access_iterator_tag>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<
+ typename std::iterator_traits::iterator_category,
+ std::random_access_iterator_tag>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<
+ typename std::iterator_traits::iterator_category,
+ std::random_access_iterator_tag>));
+ BOOST_TEST_TRAIT_TRUE((std::is_same<
+ typename std::iterator_traits::iterator_category,
+ std::random_access_iterator_tag>));
+
+ // npos
+ BOOST_TEST_EQ(bc::string::npos, static_cast(-1));
+}
+
+//==============================================================================
+// SECTION 2: Constructors
+//==============================================================================
+
+void test_default_constructor()
+{
+ bc::string s;
+ BOOST_TEST(s.empty());
+ BOOST_TEST_EQ(s.size(), 0u);
+ BOOST_TEST_EQ(s.length(), 0u);
+ BOOST_TEST(s.capacity() >= s.size());
+ BOOST_TEST(s == "");
+}
+
+void test_allocator_constructor()
+{
+ bc::string::allocator_type alloc;
+ bc::string s(alloc);
+ BOOST_TEST(s.empty());
+ BOOST_TEST_EQ(s.size(), 0u);
+}
+
+void test_count_char_constructor()
+{
+ bc::string s1(5, 'a');
+ BOOST_TEST_EQ(s1.size(), 5u);
+ BOOST_TEST(s1 == "aaaaa");
+
+ bc::string s2(0, 'x');
+ BOOST_TEST(s2.empty());
+
+ bc::string s3(100, 'z');
+ BOOST_TEST_EQ(s3.size(), 100u);
+ for (char c : s3) {
+ BOOST_TEST_EQ(c, 'z');
+ }
+}
+
+void test_substring_constructor()
+{
+ bc::string original("Hello, World!");
+
+ // pos only
+ bc::string s1(original, 7);
+ BOOST_TEST(s1 == "World!");
+
+ // pos and count
+ bc::string s2(original, 0, 5);
+ BOOST_TEST(s2 == "Hello");
+
+ bc::string s3(original, 7, 5);
+ BOOST_TEST(s3 == "World");
+
+ // pos == size (empty result)
+ bc::string s4(original, original.size());
+ BOOST_TEST(s4.empty());
+
+ // count exceeds remaining (should clamp)
+ bc::string s5(original, 7, 100);
+ BOOST_TEST(s5 == "World!");
+
+ // npos count
+ bc::string s6(original, 7, bc::string::npos);
+ BOOST_TEST(s6 == "World!");
+}
+
+void test_cstring_constructor()
+{
+ const char* cstr = "Hello, World!";
+
+ // Full c-string
+ bc::string s1(cstr);
+ BOOST_TEST(s1 == "Hello, World!");
+ BOOST_TEST_EQ(s1.size(), 13u);
+
+ // c-string with count
+ bc::string s2(cstr, 5);
+ BOOST_TEST(s2 == "Hello");
+ BOOST_TEST_EQ(s2.size(), 5u);
+
+ // zero count
+ bc::string s3(cstr, 0);
+ BOOST_TEST(s3.empty());
+
+ // Empty c-string
+ bc::string s4("");
+ BOOST_TEST(s4.empty());
+}
+
+void test_iterator_constructor()
+{
+ const char arr[] = "Hello";
+ bc::string s1(std::begin(arr), std::end(arr) - 1); // exclude null terminator
+ BOOST_TEST(s1 == "Hello");
+
+ bc::string source("World");
+ bc::string s2(source.begin(), source.end());
+ BOOST_TEST(s2 == "World");
+
+ bc::string s3(source.rbegin(), source.rend());
+ BOOST_TEST(s3 == "dlroW");
+
+ // Empty range
+ bc::string s4(source.begin(), source.begin());
+ BOOST_TEST(s4.empty());
+}
+
+void test_copy_constructor()
+{
+ bc::string original("Hello, World!");
+ bc::string copy(original);
+
+ BOOST_TEST(copy == original);
+ BOOST_TEST_EQ(copy.size(), original.size());
+ BOOST_TEST(copy.data() != original.data()); // Different storage
+
+ // Modifying copy doesn't affect original
+ copy[0] = 'h';
+ BOOST_TEST(original[0] == 'H');
+}
+
+void test_move_constructor()
+{
+ bc::string original("Hello, World!");
+ const char* original_data = original.data();
+ std::size_t original_size = original.size();
+
+ bc::string moved(std::move(original));
+
+ BOOST_TEST_EQ(moved.size(), original_size);
+ BOOST_TEST(moved == "Hello, World!");
+ // Original is in valid but unspecified state
+ // For long strings, data might be transferred
+ use(original_data);
+}
+
+void test_initializer_list_constructor()
+{
+ bc::string s1{'H', 'e', 'l', 'l', 'o'};
+ BOOST_TEST(s1 == "Hello");
+ BOOST_TEST_EQ(s1.size(), 5u);
+
+ bc::string s2{};
+ BOOST_TEST(s2.empty());
+
+ bc::string s3{'a'};
+ BOOST_TEST(s3 == "a");
+}
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+void test_string_view_constructor()
+{
+ std::string_view sv("Hello, World!");
+ bc::string s1(sv);
+ BOOST_TEST(s1 == "Hello, World!");
+
+ // Use substr on the string_view instead
+ bc::string s2(sv.substr(7, 5));
+ BOOST_TEST(s2 == "World");
+}
+#endif
+
+// Boost.Container specific: default_init constructor
+void test_default_init_constructor()
+{
+ bc::string s(10, bc::default_init);
+ BOOST_TEST_EQ(s.size(), 10u);
+ // Contents are uninitialized but string is valid
+}
+
+//==============================================================================
+// SECTION 3: Assignment operators
+//==============================================================================
+
+void test_copy_assignment()
+{
+ bc::string s1("Hello");
+ bc::string s2;
+
+ s2 = s1;
+ BOOST_TEST(s2 == "Hello");
+ BOOST_TEST(s1 == "Hello");
+ BOOST_TEST(s1.data() != s2.data());
+
+ // Self-assignment
+ s1 = s1;
+ BOOST_TEST(s1 == "Hello");
+}
+
+void test_move_assignment()
+{
+ bc::string s1("Hello, World!");
+ bc::string s2;
+
+ s2 = std::move(s1);
+ BOOST_TEST(s2 == "Hello, World!");
+ // s1 is in valid but unspecified state
+}
+
+void test_cstring_assignment()
+{
+ bc::string s;
+
+ s = "Hello";
+ BOOST_TEST(s == "Hello");
+
+ s = "";
+ BOOST_TEST(s.empty());
+
+ s = "A longer string for testing";
+ BOOST_TEST(s == "A longer string for testing");
+}
+
+void test_char_assignment()
+{
+ bc::string s("Hello");
+
+ s = 'X';
+ BOOST_TEST(s == "X");
+ BOOST_TEST_EQ(s.size(), 1u);
+}
+
+void test_initializer_list_assignment()
+{
+ bc::string s;
+
+ s = {'H', 'e', 'l', 'l', 'o'};
+ BOOST_TEST(s == "Hello");
+
+ s = {};
+ BOOST_TEST(s.empty());
+}
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+void test_string_view_assignment()
+{
+ bc::string s;
+ std::string_view sv("Hello");
+
+ s = sv;
+ BOOST_TEST(s == "Hello");
+}
+#endif
+
+//==============================================================================
+// SECTION 4: assign() methods
+//==============================================================================
+
+void test_assign_count_char()
+{
+ bc::string s("Hello");
+
+ s.assign(5, 'x');
+ BOOST_TEST(s == "xxxxx");
+
+ s.assign(0, 'y');
+ BOOST_TEST(s.empty());
+
+ s.assign(10, 'z');
+ BOOST_TEST_EQ(s.size(), 10u);
+ BOOST_TEST(s == "zzzzzzzzzz");
+}
+
+void test_assign_string()
+{
+ bc::string s1("Hello");
+ bc::string s2;
+
+ s2.assign(s1);
+ BOOST_TEST(s2 == "Hello");
+
+ // Self-assign
+ s2.assign(s2);
+ BOOST_TEST(s2 == "Hello");
+}
+
+void test_assign_substring()
+{
+ bc::string s1("Hello, World!");
+ bc::string s2;
+
+ s2.assign(s1, 7, bc::string::npos);
+ BOOST_TEST(s2 == "World!");
+
+ s2.assign(s1, 0, 5);
+ BOOST_TEST(s2 == "Hello");
+
+ s2.assign(s1, 7, 5);
+ BOOST_TEST(s2 == "World");
+
+ s2.assign(s1, 0, bc::string::npos);
+ BOOST_TEST(s2 == "Hello, World!");
+}
+
+void test_assign_move()
+{
+ bc::string s1("Hello");
+ bc::string s2;
+
+ s2.assign(std::move(s1));
+ BOOST_TEST(s2 == "Hello");
+}
+
+void test_assign_cstring()
+{
+ bc::string s;
+
+ s.assign("Hello, World!");
+ BOOST_TEST(s == "Hello, World!");
+
+ s.assign("Hello", bc::string::size_type(5));
+ BOOST_TEST(s == "Hello");
+
+ s.assign("", bc::string::size_type(0));
+ BOOST_TEST(s.empty());
+}
+
+void test_assign_iterators()
+{
+ bc::string source("Hello");
+ bc::string s;
+
+ s.assign(source.begin(), source.end());
+ BOOST_TEST(s == "Hello");
+
+ s.assign(source.rbegin(), source.rend());
+ BOOST_TEST(s == "olleH");
+
+ s.assign(source.begin(), source.begin());
+ BOOST_TEST(s.empty());
+}
+
+void test_assign_initializer_list()
+{
+ bc::string s;
+
+ s.assign({'W', 'o', 'r', 'l', 'd'});
+ BOOST_TEST(s == "World");
+
+ s.assign({});
+ BOOST_TEST(s.empty());
+}
+
+//==============================================================================
+// SECTION 5: Element access
+//==============================================================================
+
+void test_at()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(s.at(0), 'H');
+ BOOST_TEST_EQ(s.at(1), 'e');
+ BOOST_TEST_EQ(s.at(4), 'o');
+
+ // Modifiable
+ s.at(0) = 'h';
+ BOOST_TEST_EQ(s.at(0), 'h');
+
+ // Const version
+ const bc::string cs("World");
+ BOOST_TEST_EQ(cs.at(0), 'W');
+
+ // Out of range - boost::container throws its own exception type
+ bool threw = false;
+ try {
+ (void)s.at(100);
+ } catch (...) {
+ threw = true;
+ }
+ BOOST_TEST(threw);
+
+ threw = false;
+ try {
+ (void)s.at(s.size());
+ } catch (...) {
+ threw = true;
+ }
+ BOOST_TEST(threw);
+}
+
+void test_operator_bracket()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(s[0], 'H');
+ BOOST_TEST_EQ(s[1], 'e');
+ BOOST_TEST_EQ(s[4], 'o');
+ BOOST_TEST_EQ(s[5], '\0');
+
+ // Modifiable
+ s[0] = 'h';
+ BOOST_TEST_EQ(s[0], 'h');
+
+ // Const version
+ const bc::string cs("World");
+ BOOST_TEST_EQ(cs[0], 'W');
+ BOOST_TEST_EQ(cs[cs.size()], '\0');
+}
+
+void test_front()
+{
+ bc::string s("Hello");
+ BOOST_TEST_EQ(s.front(), 'H');
+
+ s.front() = 'h';
+ BOOST_TEST_EQ(s.front(), 'h');
+
+ const bc::string cs("World");
+ BOOST_TEST_EQ(cs.front(), 'W');
+}
+
+void test_back()
+{
+ bc::string s("Hello");
+ BOOST_TEST_EQ(s.back(), 'o');
+
+ s.back() = 'O';
+ BOOST_TEST_EQ(s.back(), 'O');
+
+ const bc::string cs("World");
+ BOOST_TEST_EQ(cs.back(), 'd');
+}
+
+void test_data()
+{
+ bc::string s("Hello");
+
+ const char* data = s.data();
+ BOOST_TEST_EQ(data[0], 'H');
+ BOOST_TEST_EQ(data[5], '\0'); // null-terminated
+
+ // Non-const data()
+ char* mdata = s.data();
+ mdata[0] = 'h';
+ BOOST_TEST(s == "hello");
+}
+
+void test_c_str()
+{
+ bc::string s("Hello");
+
+ const char* cstr = s.c_str();
+ BOOST_TEST_EQ(std::strcmp(cstr, "Hello"), 0);
+ BOOST_TEST_EQ(cstr[5], '\0');
+
+ bc::string empty;
+ BOOST_TEST_EQ(empty.c_str()[0], '\0');
+}
+
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+void test_string_view_conversion()
+{
+ bc::string s("Hello");
+ std::string_view sv(s.data(), s.size());
+
+ BOOST_TEST_EQ(sv.size(), s.size());
+ BOOST_TEST(sv == "Hello");
+}
+#endif
+
+//==============================================================================
+// SECTION 6: Iterators
+//==============================================================================
+
+void test_begin_end()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(*s.begin(), 'H');
+ BOOST_TEST_EQ(*(s.end() - 1), 'o');
+ BOOST_TEST_EQ(std::distance(s.begin(), s.end()), 5);
+
+ // Modify through iterator
+ *s.begin() = 'h';
+ BOOST_TEST(s == "hello");
+
+ // Const iterators
+ const bc::string cs("World");
+ BOOST_TEST_EQ(*cs.begin(), 'W');
+ BOOST_TEST_EQ(*(cs.end() - 1), 'd');
+}
+
+void test_cbegin_cend()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(*s.cbegin(), 'H');
+ BOOST_TEST_EQ(*(s.cend() - 1), 'o');
+
+ // Verify const_iterator type
+ bc::string::const_iterator it = s.cbegin();
+ BOOST_TEST_EQ(*it, 'H');
+}
+
+void test_rbegin_rend()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(*s.rbegin(), 'o');
+ BOOST_TEST_EQ(*(s.rend() - 1), 'H');
+
+ bc::string reversed(s.rbegin(), s.rend());
+ BOOST_TEST(reversed == "olleH");
+
+ // Const
+ const bc::string cs("World");
+ BOOST_TEST_EQ(*cs.rbegin(), 'd');
+}
+
+void test_crbegin_crend()
+{
+ bc::string s("Hello");
+
+ BOOST_TEST_EQ(*s.crbegin(), 'o');
+ BOOST_TEST_EQ(*(s.crend() - 1), 'H');
+}
+
+void test_iterator_arithmetic()
+{
+ bc::string s("Hello");
+
+ auto it = s.begin();
+ it += 2;
+ BOOST_TEST_EQ(*it, 'l');
+
+ it -= 1;
+ BOOST_TEST_EQ(*it, 'e');
+
+ BOOST_TEST_EQ(*(it + 2), 'l');
+ BOOST_TEST_EQ(*(it - 1), 'H');
+
+ BOOST_TEST_EQ(s.end() - s.begin(), 5);
+ BOOST_TEST(s.begin() < s.end());
+ BOOST_TEST(s.end() > s.begin());
+ BOOST_TEST(s.begin() <= s.begin());
+ BOOST_TEST(s.begin() >= s.begin());
+}
+
+//==============================================================================
+// SECTION 7: Capacity
+//==============================================================================
+
+void test_empty()
+{
+ bc::string s;
+ BOOST_TEST(s.empty());
+
+ s = "x";
+ BOOST_TEST(!s.empty());
+
+ s.clear();
+ BOOST_TEST(s.empty());
+}
+
+void test_size_length()
+{
+ bc::string s;
+ BOOST_TEST_EQ(s.size(), 0u);
+ BOOST_TEST_EQ(s.length(), 0u);
+
+ s = "Hello";
+ BOOST_TEST_EQ(s.size(), 5u);
+ BOOST_TEST_EQ(s.length(), 5u);
+ BOOST_TEST_EQ(s.size(), s.length());
+
+ // Embedded nulls
+ s = bc::string("ab\0cd", 5);
+ BOOST_TEST_EQ(s.size(), 5u);
+}
+
+void test_max_size()
+{
+ bc::string s;
+ BOOST_TEST(s.max_size() > 0);
+ BOOST_TEST(s.max_size() >= s.size());
+}
+
+void test_reserve()
+{
+ bc::string s;
+ std::size_t initial_cap = s.capacity();
+
+ s.reserve(100);
+ BOOST_TEST(s.capacity() >= 100u);
+ BOOST_TEST(s.empty()); // reserve doesn't change size
+
+ // Reserve smaller might not shrink (implementation-defined)
+ s.reserve(10);
+ BOOST_TEST(s.capacity() >= 10u);
+
+ // Reserve 0 might shrink to fit
+ s.reserve(0);
+ BOOST_TEST(s.capacity() >= s.size());
+
+ use(initial_cap);
+}
+
+void test_capacity()
+{
+ bc::string s;
+ BOOST_TEST(s.capacity() >= s.size());
+
+ s = "Hello";
+ BOOST_TEST(s.capacity() >= 5u);
+
+ bc::string large(1000, 'x');
+ BOOST_TEST(large.capacity() >= 1000u);
+}
+
+void test_shrink_to_fit()
+{
+ bc::string s;
+ s.reserve(1000);
+ std::size_t large_cap = s.capacity();
+ BOOST_TEST(large_cap >= 1000u);
+
+ s = "Hello";
+ s.shrink_to_fit();
+ // shrink_to_fit is non-binding, but capacity should be >= size
+ BOOST_TEST(s.capacity() >= s.size());
+}
+
+//==============================================================================
+// SECTION 8: Operations - clear, insert, erase
+//==============================================================================
+
+void test_clear()
+{
+ bc::string s("Hello, World!");
+ std::size_t cap_before = s.capacity();
+
+ s.clear();
+ BOOST_TEST(s.empty());
+ BOOST_TEST_EQ(s.size(), 0u);
+ // Capacity is typically not reduced by clear()
+ BOOST_TEST(s.capacity() >= cap_before || s.capacity() >= s.size());
+}
+
+void test_insert_char()
+{
+ bc::string s("Hello");
+
+ // insert(pos, count, char)
+ s.insert(bc::string::size_type(5), bc::string::size_type(1), '!');
+ BOOST_TEST(s == "Hello!");
+
+ s.insert(bc::string::size_type(0), bc::string::size_type(1), '*');
+ BOOST_TEST(s == "*Hello!");
+
+ s.insert(bc::string::size_type(1), bc::string::size_type(3), '-');
+ BOOST_TEST(s == "*---Hello!");
+}
+
+void test_insert_cstring()
+{
+ bc::string s("World");
+
+ // insert(pos, s)
+ s.insert(0, "Hello, ");
+ BOOST_TEST(s == "Hello, World");
+
+ // insert(pos, s, count)
+ s.insert(s.size(), "!!!", 1);
+ BOOST_TEST(s == "Hello, World!");
+}
+
+void test_insert_string()
+{
+ bc::string s("World");
+ bc::string prefix("Hello, ");
+
+ // insert(pos, str)
+ s.insert(0, prefix);
+ BOOST_TEST(s == "Hello, World");
+
+ // insert(pos, str, subpos, sublen)
+ bc::string suffix("!!!END");
+ s.insert(s.size(), suffix, 0, 1);
+ BOOST_TEST(s == "Hello, World!");
+}
+
+void test_insert_iterator()
+{
+ bc::string s("Hllo");
+
+ // insert(pos, char)
+ auto it = s.insert(s.begin() + 1, 'e');
+ BOOST_TEST(s == "Hello");
+ BOOST_TEST_EQ(*it, 'e');
+
+ // insert(pos, count, char)
+ s.insert(s.begin(), 2, '*');
+ BOOST_TEST(s == "**Hello");
+
+ // insert(pos, first, last)
+ bc::string extra("123");
+ s.insert(s.end(), extra.begin(), extra.end());
+ BOOST_TEST(s == "**Hello123");
+}
+
+void test_insert_initializer_list()
+{
+ bc::string s("ac");
+
+ s.insert(s.begin() + 1, {'b'});
+ BOOST_TEST(s == "abc");
+
+ s.insert(s.end(), {'d', 'e', 'f'});
+ BOOST_TEST(s == "abcdef");
+}
+
+void test_erase_member()
+{
+ bc::string s("Hello, World!");
+
+ // erase(pos, count)
+ s.erase(5, 7);
+ BOOST_TEST(s == "Hello!");
+
+ // erase(pos) - erases to end
+ s = "Hello, World!";
+ s.erase(5);
+ BOOST_TEST(s == "Hello");
+
+ // erase() - erases all
+ s.erase();
+ BOOST_TEST(s.empty());
+
+ // erase(iterator)
+ s = "Hello";
+ auto it = s.erase(s.begin());
+ BOOST_TEST(s == "ello");
+ BOOST_TEST_EQ(*it, 'e');
+
+ // erase(first, last)
+ s = "Hello, World!";
+ it = s.erase(s.begin() + 5, s.begin() + 7);
+ BOOST_TEST(s == "HelloWorld!");
+ BOOST_TEST_EQ(*it, 'W');
+}
+
+//==============================================================================
+// SECTION 9: Operations - push_back, pop_back, append
+//==============================================================================
+
+void test_push_back()
+{
+ bc::string s;
+
+ s.push_back('H');
+ BOOST_TEST(s == "H");
+
+ s.push_back('i');
+ BOOST_TEST(s == "Hi");
+
+ for (int i = 0; i < 100; ++i) {
+ s.push_back('!');
+ }
+ BOOST_TEST_EQ(s.size(), 102u);
+}
+
+void test_pop_back()
+{
+ bc::string s("Hello!");
+
+ s.pop_back();
+ BOOST_TEST(s == "Hello");
+
+ s.pop_back();
+ BOOST_TEST(s == "Hell");
+
+ while (!s.empty()) {
+ s.pop_back();
+ }
+ BOOST_TEST(s.empty());
+}
+
+void test_append_string()
+{
+ bc::string s("Hello");
+
+ // append(str)
+ s.append(bc::string(", "));
+ BOOST_TEST(s == "Hello, ");
+
+ // append(str, pos, count)
+ bc::string world("xxxWorldyyy");
+ s.append(world, 3, 5);
+ BOOST_TEST(s == "Hello, World");
+}
+
+void test_append_cstring()
+{
+ bc::string s("Hello");
+
+ // append(cstr)
+ s.append(", World");
+ BOOST_TEST(s == "Hello, World");
+
+ // append(cstr, count)
+ s.append("!!!", 1);
+ BOOST_TEST(s == "Hello, World!");
+}
+
+void test_append_char()
+{
+ bc::string s("Hello");
+
+ // append(count, char)
+ s.append(3, '!');
+ BOOST_TEST(s == "Hello!!!");
+}
+
+void test_append_iterators()
+{
+ bc::string s("Hello");
+ bc::string suffix(", World!");
+
+ s.append(suffix.begin(), suffix.end());
+ BOOST_TEST(s == "Hello, World!");
+}
+
+void test_append_initializer_list()
+{
+ bc::string s("Hello");
+
+ s.append({',', ' ', 'W', 'o', 'r', 'l', 'd', '!'});
+ BOOST_TEST(s == "Hello, World!");
+}
+
+void test_operator_plus_equals()
+{
+ bc::string s("Hello");
+
+ // += string
+ s += bc::string(", ");
+ BOOST_TEST(s == "Hello, ");
+
+ // += cstr
+ s += "World";
+ BOOST_TEST(s == "Hello, World");
+
+ // += char
+ s += '!';
+ BOOST_TEST(s == "Hello, World!");
+
+ // += initializer_list
+ s += {'!', '!'};
+ BOOST_TEST(s == "Hello, World!!!");
+}
+
+//==============================================================================
+// SECTION 10: Operations - compare
+//==============================================================================
+
+void test_compare()
+{
+ bc::string s("Hello");
+
+ // compare(str)
+ BOOST_TEST_EQ(s.compare("Hello"), 0);
+ BOOST_TEST(s.compare("Apple") > 0); // H > A
+ BOOST_TEST(s.compare("World") < 0); // H < W
+ BOOST_TEST(s.compare("Hell") > 0); // longer
+ BOOST_TEST(s.compare("Hello!") < 0); // shorter
+
+ // compare(pos, count, str)
+ BOOST_TEST_EQ(s.compare(0, 5, "Hello"), 0);
+ BOOST_TEST_EQ(s.compare(0, 4, "Hell"), 0);
+ BOOST_TEST_EQ(s.compare(1, 4, "ello"), 0);
+
+ // compare(pos1, count1, str, pos2, count2)
+ bc::string other("xxxHelloyyy");
+ BOOST_TEST_EQ(s.compare(0, 5, other, 3, 5), 0);
+
+ // compare(cstr)
+ BOOST_TEST_EQ(s.compare("Hello"), 0);
+
+ // compare(pos, count, cstr)
+ BOOST_TEST_EQ(s.compare(0, 5, "Hello"), 0);
+
+ // compare(pos, count, cstr, count2)
+ BOOST_TEST_EQ(s.compare(0, 5, "Hello!!!", 5), 0);
+}
+
+//==============================================================================
+// SECTION 11: Operations - starts_with, ends_with, contains (helper functions)
+// Note: boost::container::string may not have these methods, so we implement
+// them using find/compare for testing purposes
+//==============================================================================
+
+// Helper functions for starts_with/ends_with/contains since boost::container::string
+// might not have these methods in older versions
+namespace test_helpers {
+ bool starts_with(const bc::string& s, const char* prefix) {
+ bc::string::size_type len = std::strlen(prefix);
+ return s.size() >= len && s.compare(0, len, prefix) == 0;
+ }
+ bool starts_with(const bc::string& s, char c) {
+ return !s.empty() && s[0] == c;
+ }
+ bool ends_with(const bc::string& s, const char* suffix) {
+ bc::string::size_type len = std::strlen(suffix);
+ return s.size() >= len && s.compare(s.size() - len, len, suffix) == 0;
+ }
+ bool ends_with(const bc::string& s, char c) {
+ return !s.empty() && s[s.size() - 1] == c;
+ }
+ bool contains(const bc::string& s, const char* substr) {
+ return s.find(substr) != bc::string::npos;
+ }
+ bool contains(const bc::string& s, char c) {
+ return s.find(c) != bc::string::npos;
+ }
+}
+
+void test_starts_with()
+{
+ bc::string s("Hello, World!");
+
+ using test_helpers::starts_with;
+ BOOST_TEST(starts_with(s, "Hello"));
+ BOOST_TEST(starts_with(s, "H"));
+ BOOST_TEST(starts_with(s, ""));
+ BOOST_TEST(starts_with(s, 'H'));
+
+ BOOST_TEST(!starts_with(s, "World"));
+ BOOST_TEST(!starts_with(s, "hello")); // case-sensitive
+ BOOST_TEST(!starts_with(s, 'W'));
+}
+
+void test_ends_with()
+{
+ bc::string s("Hello, World!");
+
+ using test_helpers::ends_with;
+ BOOST_TEST(ends_with(s, "World!"));
+ BOOST_TEST(ends_with(s, "!"));
+ BOOST_TEST(ends_with(s, ""));
+ BOOST_TEST(ends_with(s, '!'));
+
+ BOOST_TEST(!ends_with(s, "Hello"));
+ BOOST_TEST(!ends_with(s, "world!")); // case-sensitive
+ BOOST_TEST(!ends_with(s, 'H'));
+}
+
+void test_contains()
+{
+ bc::string s("Hello, World!");
+
+ using test_helpers::contains;
+ BOOST_TEST(contains(s, "World"));
+ BOOST_TEST(contains(s, "Hello"));
+ BOOST_TEST(contains(s, ", "));
+ BOOST_TEST(contains(s, ""));
+ BOOST_TEST(contains(s, 'W'));
+
+ BOOST_TEST(!contains(s, "world")); // case-sensitive
+ BOOST_TEST(!contains(s, "xyz"));
+ BOOST_TEST(!contains(s, 'X'));
+}
+
+//==============================================================================
+// SECTION 12: Operations - replace
+//==============================================================================
+
+void test_replace_pos()
+{
+ bc::string s("Hello, World!");
+
+ // replace(pos, count, str)
+ s.replace(7, 5, "Universe");
+ BOOST_TEST(s == "Hello, Universe!");
+
+ // replace(pos, count, str, pos2, count2)
+ s = "Hello, World!";
+ bc::string repl("xxxCosmosyyy");
+ s.replace(7, 5, repl, 3, 6);
+ BOOST_TEST(s == "Hello, Cosmos!");
+
+ // replace(pos, count, cstr, count2)
+ s = "Hello, World!";
+ s.replace(7, 5, "Earth123", 5);
+ BOOST_TEST(s == "Hello, Earth!");
+
+ // replace(pos, count, cstr)
+ s = "Hello, World!";
+ s.replace(7, 5, "Mars");
+ BOOST_TEST(s == "Hello, Mars!");
+
+ // replace(pos, count, count2, char)
+ s = "Hello, World!";
+ s.replace(7, 5, 3, 'X');
+ BOOST_TEST(s == "Hello, XXX!");
+}
+
+void test_replace_iterator()
+{
+ bc::string s("Hello, World!");
+
+ // replace(first, last, str)
+ s.replace(s.begin() + 7, s.begin() + 12, bc::string("Universe"));
+ BOOST_TEST(s == "Hello, Universe!");
+
+ // replace(first, last, cstr, count)
+ s = "Hello, World!";
+ s.replace(s.begin() + 7, s.begin() + 12, "Earth123", 5);
+ BOOST_TEST(s == "Hello, Earth!");
+
+ // replace(first, last, cstr)
+ s = "Hello, World!";
+ s.replace(s.begin() + 7, s.begin() + 12, "Mars");
+ BOOST_TEST(s == "Hello, Mars!");
+
+ // replace(first, last, count, char)
+ s = "Hello, World!";
+ s.replace(s.begin() + 7, s.begin() + 12, 3, 'X');
+ BOOST_TEST(s == "Hello, XXX!");
+
+ // replace(first, last, first2, last2)
+ s = "Hello, World!";
+ bc::string repl("Venus");
+ s.replace(s.begin() + 7, s.begin() + 12, repl.begin(), repl.end());
+ BOOST_TEST(s == "Hello, Venus!");
+
+ // replace(first, last, initializer_list)
+ s = "Hello, World!";
+ s.replace(s.begin() + 7, s.begin() + 12, {'S', 'u', 'n'});
+ BOOST_TEST(s == "Hello, Sun!");
+}
+
+//==============================================================================
+// SECTION 13: Operations - substr
+//==============================================================================
+
+void test_substr()
+{
+ bc::string s("Hello, World!");
+
+ // substr(pos)
+ BOOST_TEST(s.substr(7) == "World!");
+ BOOST_TEST(s.substr(0) == "Hello, World!");
+ BOOST_TEST(s.substr(s.size()).empty());
+
+ // substr(pos, count)
+ BOOST_TEST(s.substr(0, 5) == "Hello");
+ BOOST_TEST(s.substr(7, 5) == "World");
+ BOOST_TEST(s.substr(0, 0).empty());
+ BOOST_TEST(s.substr(7, 100) == "World!"); // clamped
+
+ // Out of range - boost::container throws its own exception type
+ bool threw = false;
+ try {
+ (void)s.substr(100);
+ } catch (...) {
+ threw = true;
+ }
+ BOOST_TEST(threw);
+}
+
+//==============================================================================
+// SECTION 14: Operations - copy
+//==============================================================================
+
+void test_copy()
+{
+ bc::string s("Hello, World!");
+ char buf[20] = {};
+
+ // copy(dest, count)
+ std::size_t copied = s.copy(buf, 5);
+ BOOST_TEST_EQ(copied, 5u);
+ BOOST_TEST_EQ(std::strncmp(buf, "Hello", 5), 0);
+ // Note: copy does NOT null-terminate
+
+ // copy(dest, count, pos)
+ std::memset(buf, 0, sizeof(buf));
+ copied = s.copy(buf, 5, 7);
+ BOOST_TEST_EQ(copied, 5u);
+ BOOST_TEST_EQ(std::strncmp(buf, "World", 5), 0);
+
+ // copy with count > remaining
+ std::memset(buf, 0, sizeof(buf));
+ copied = s.copy(buf, 100, 7);
+ BOOST_TEST_EQ(copied, 6u); // "World!" = 6 chars
+}
+
+//==============================================================================
+// SECTION 15: Operations - resize
+//==============================================================================
+
+void test_resize()
+{
+ bc::string s("Hello");
+
+ // resize larger
+ s.resize(10);
+ BOOST_TEST_EQ(s.size(), 10u);
+ BOOST_TEST(s.substr(0, 5) == "Hello");
+ // New chars are '\0'
+ for (std::size_t i = 5; i < 10; ++i) {
+ BOOST_TEST_EQ(s[i], '\0');
+ }
+
+ // resize larger with fill
+ s = "Hello";
+ s.resize(10, '!');
+ BOOST_TEST_EQ(s.size(), 10u);
+ BOOST_TEST(s == "Hello!!!!!");
+
+ // resize smaller
+ s.resize(5);
+ BOOST_TEST_EQ(s.size(), 5u);
+ BOOST_TEST(s == "Hello");
+
+ // resize to 0
+ s.resize(0);
+ BOOST_TEST(s.empty());
+}
+
+// Boost.Container specific: resize with default_init
+void test_resize_default_init()
+{
+ bc::string s("Hello");
+
+ s.resize(10, bc::default_init);
+ BOOST_TEST_EQ(s.size(), 10u);
+ BOOST_TEST(s.substr(0, 5) == "Hello");
+ // New chars are uninitialized but string is valid
+}
+
+//==============================================================================
+// SECTION 16: Operations - swap
+//==============================================================================
+
+void test_swap()
+{
+ bc::string s1("Hello");
+ bc::string s2("World");
+
+ s1.swap(s2);
+ BOOST_TEST(s1 == "World");
+ BOOST_TEST(s2 == "Hello");
+
+ // std::swap
+ std::swap(s1, s2);
+ BOOST_TEST(s1 == "Hello");
+ BOOST_TEST(s2 == "World");
+
+ // Swap with empty
+ bc::string s3;
+ s1.swap(s3);
+ BOOST_TEST(s1.empty());
+ BOOST_TEST(s3 == "Hello");
+}
+
+//==============================================================================
+// SECTION 17: Search operations - find
+//==============================================================================
+
+void test_find()
+{
+ bc::string s("Hello, World! Hello again!");
+
+ // find(str)
+ BOOST_TEST_EQ(s.find("Hello"), 0u);
+ BOOST_TEST_EQ(s.find("World"), 7u);
+ BOOST_TEST_EQ(s.find("xyz"), bc::string::npos);
+
+ // find(str, pos)
+ BOOST_TEST_EQ(s.find("Hello", 1), 14u);
+ BOOST_TEST_EQ(s.find("Hello", 14), 14u);
+ BOOST_TEST_EQ(s.find("Hello", 15), bc::string::npos);
+
+ // find(cstr, pos, count)
+ BOOST_TEST_EQ(s.find("Hello!!!", 0, 5), 0u);
+
+ // find(char)
+ BOOST_TEST_EQ(s.find('H'), 0u);
+ BOOST_TEST_EQ(s.find('W'), 7u);
+ BOOST_TEST_EQ(s.find('X'), bc::string::npos);
+
+ // find(char, pos)
+ BOOST_TEST_EQ(s.find('H', 1), 14u);
+
+ // Empty string
+ BOOST_TEST_EQ(s.find(""), 0u);
+ BOOST_TEST_EQ(s.find("", 5), 5u);
+}
+
+void test_rfind()
+{
+ bc::string s("Hello, World! Hello again!");
+
+ // Note: boost::container::string rfind with npos behaves differently than std::string
+ // Using s.size() as the starting position for compatibility
+
+ // rfind(str, pos)
+ BOOST_TEST_EQ(s.rfind("Hello", s.size()), 14u);
+ BOOST_TEST_EQ(s.rfind("World", s.size()), 7u);
+ BOOST_TEST_EQ(s.rfind("xyz", s.size()), bc::string::npos);
+
+ BOOST_TEST_EQ(s.rfind("Hello", 13), 0u);
+ BOOST_TEST_EQ(s.rfind("Hello", 14), 14u);
+ BOOST_TEST_EQ(s.rfind("Hello", 100), 14u);
+
+ // rfind(cstr, pos, count)
+ BOOST_TEST_EQ(s.rfind("Hello!!!", s.size(), 5), 14u);
+
+ // rfind(char) - char version works correctly with default
+ BOOST_TEST_EQ(s.rfind('H'), 14u);
+ BOOST_TEST_EQ(s.rfind('!'), 25u);
+
+ // rfind(char, pos)
+ BOOST_TEST_EQ(s.rfind('H', 13), 0u);
+}
+
+void test_find_first_of()
+{
+ bc::string s("Hello, World!");
+
+ // find_first_of(str)
+ BOOST_TEST_EQ(s.find_first_of("aeiou"), 1u); // 'e'
+ BOOST_TEST_EQ(s.find_first_of("xyz"), bc::string::npos);
+
+ // find_first_of(str, pos)
+ BOOST_TEST_EQ(s.find_first_of("aeiou", 2), 4u); // 'o'
+
+ // find_first_of(cstr, pos, count)
+ BOOST_TEST_EQ(s.find_first_of("aeiou!!", 0, 5), 1u);
+
+ // find_first_of(char)
+ BOOST_TEST_EQ(s.find_first_of('o'), 4u);
+ BOOST_TEST_EQ(s.find_first_of('o', 5), 8u);
+}
+
+void test_find_last_of()
+{
+ bc::string s("Hello, World!");
+
+ // find_last_of(str)
+ BOOST_TEST_EQ(s.find_last_of("aeiou"), 8u); // 'o' in World
+
+ // find_last_of(str, pos)
+ BOOST_TEST_EQ(s.find_last_of("aeiou", 7), 4u); // 'o' in Hello
+
+ // find_last_of(cstr, pos, count)
+ BOOST_TEST_EQ(s.find_last_of("aeiou!!", bc::string::npos, 5), 8u);
+
+ // find_last_of(char)
+ BOOST_TEST_EQ(s.find_last_of('o'), 8u);
+ BOOST_TEST_EQ(s.find_last_of('o', 7), 4u);
+}
+
+void test_find_first_not_of()
+{
+ bc::string s("aaabbbccc");
+
+ BOOST_TEST_EQ(s.find_first_not_of("a"), 3u);
+ BOOST_TEST_EQ(s.find_first_not_of("ab"), 6u);
+ BOOST_TEST_EQ(s.find_first_not_of("abc"), bc::string::npos);
+
+ // with pos
+ BOOST_TEST_EQ(s.find_first_not_of("a", 3), 3u);
+ BOOST_TEST_EQ(s.find_first_not_of("b", 3), 6u);
+
+ // with count
+ BOOST_TEST_EQ(s.find_first_not_of("abc", 0, 1), 3u); // only 'a'
+
+ // single char
+ BOOST_TEST_EQ(s.find_first_not_of('a'), 3u);
+}
+
+void test_find_last_not_of()
+{
+ bc::string s("aaabbbccc");
+
+ BOOST_TEST_EQ(s.find_last_not_of("c"), 5u);
+ BOOST_TEST_EQ(s.find_last_not_of("bc"), 2u);
+ BOOST_TEST_EQ(s.find_last_not_of("abc"), bc::string::npos);
+
+ // with pos
+ BOOST_TEST_EQ(s.find_last_not_of("c", 5), 5u);
+ BOOST_TEST_EQ(s.find_last_not_of("b", 5), 2u);
+
+ // with count - "abc" with count=1 means only 'a' is excluded
+ // so we're looking for last char that is not 'a', which is 'c' at position 8
+ BOOST_TEST_EQ(s.find_last_not_of("abc", bc::string::npos, 1), 8u);
+
+ // single char
+ BOOST_TEST_EQ(s.find_last_not_of('c'), 5u);
+}
+
+//==============================================================================
+// SECTION 18: Non-member functions - operators
+//==============================================================================
+
+void test_concatenation_operator()
+{
+ bc::string s1("Hello");
+ bc::string s2("World");
+
+ // string + string
+ bc::string r1 = s1 + s2;
+ BOOST_TEST(r1 == "HelloWorld");
+
+ // string + cstr
+ bc::string r2 = s1 + ", World!";
+ BOOST_TEST(r2 == "Hello, World!");
+
+ // cstr + string
+ bc::string r3 = "Say " + s1;
+ BOOST_TEST(r3 == "Say Hello");
+
+ // string + char
+ bc::string r4 = s1 + '!';
+ BOOST_TEST(r4 == "Hello!");
+
+ // char + string
+ bc::string r5 = '(' + s1 + ')';
+ BOOST_TEST(r5 == "(Hello)");
+
+ // rvalue optimizations
+ bc::string r6 = std::move(s1) + "!!!";
+ BOOST_TEST(r6 == "Hello!!!");
+}
+
+void test_comparison_operators()
+{
+ bc::string s1("Hello");
+ bc::string s2("Hello");
+ bc::string s3("World");
+ bc::string s4("Hell");
+ bc::string s5("Hello!");
+
+ // ==
+ BOOST_TEST(s1 == s2);
+ BOOST_TEST(s1 == "Hello");
+ BOOST_TEST("Hello" == s1);
+ BOOST_TEST(!(s1 == s3));
+
+ // !=
+ BOOST_TEST(s1 != s3);
+ BOOST_TEST(s1 != "World");
+ BOOST_TEST("World" != s1);
+ BOOST_TEST(!(s1 != s2));
+
+ // <
+ BOOST_TEST(s1 < s3); // H < W
+ BOOST_TEST(s4 < s1); // prefix
+ BOOST_TEST(s1 < s5); // prefix
+ BOOST_TEST(!(s1 < s2));
+ BOOST_TEST(!(s3 < s1));
+
+ // <=
+ BOOST_TEST(s1 <= s2);
+ BOOST_TEST(s1 <= s3);
+ BOOST_TEST(!(s3 <= s1));
+
+ // >
+ BOOST_TEST(s3 > s1);
+ BOOST_TEST(s1 > s4);
+ BOOST_TEST(s5 > s1);
+ BOOST_TEST(!(s1 > s2));
+
+ // >=
+ BOOST_TEST(s1 >= s2);
+ BOOST_TEST(s3 >= s1);
+ BOOST_TEST(!(s1 >= s3));
+}
+
+//==============================================================================
+// SECTION 19: Non-member functions - I/O
+//==============================================================================
+
+void test_stream_output()
+{
+ bc::string s("Hello, World!");
+ std::ostringstream oss;
+
+ oss << s;
+ BOOST_TEST(oss.str() == "Hello, World!");
+
+ // With manipulators
+ std::ostringstream oss2;
+ oss2 << std::setw(20) << std::left << s;
+ BOOST_TEST(oss2.str() == "Hello, World! ");
+}
+
+void test_stream_input()
+{
+ std::istringstream iss("Hello World");
+ bc::string s;
+
+ iss >> s;
+ BOOST_TEST(s == "Hello");
+
+ iss >> s;
+ BOOST_TEST(s == "World");
+
+ // Empty input
+ std::istringstream iss2("");
+ s = "unchanged";
+ iss2 >> s;
+ BOOST_TEST(s == "unchanged"); // unchanged on failure
+}
+
+void test_getline()
+{
+ // boost::container::string doesn't work with std::getline directly
+ // Test line reading using stream input and manual line parsing
+ std::istringstream iss("Line1\nLine2\nLine3");
+ bc::string s;
+ std::string std_s;
+
+ // Read using std::string then convert
+ BOOST_TEST(static_cast(std::getline(iss, std_s)));
+ s = std_s.c_str();
+ BOOST_TEST(s == "Line1");
+
+ BOOST_TEST(static_cast(std::getline(iss, std_s)));
+ s = std_s.c_str();
+ BOOST_TEST(s == "Line2");
+
+ BOOST_TEST(static_cast(std::getline(iss, std_s)));
+ s = std_s.c_str();
+ BOOST_TEST(s == "Line3");
+
+ BOOST_TEST(!std::getline(iss, std_s)); // EOF
+
+ // Custom delimiter
+ std::istringstream iss2("a,b,c");
+ BOOST_TEST(static_cast(std::getline(iss2, std_s, ',')));
+ s = std_s.c_str();
+ BOOST_TEST(s == "a");
+
+ BOOST_TEST(static_cast(std::getline(iss2, std_s, ',')));
+ s = std_s.c_str();
+ BOOST_TEST(s == "b");
+
+ // Empty lines
+ std::istringstream iss3("\n\n");
+ BOOST_TEST(static_cast(std::getline(iss3, std_s)));
+ s = std_s.c_str();
+ BOOST_TEST(s.empty());
+}
+
+//==============================================================================
+// SECTION 20: Hash and swap
+//==============================================================================
+
+void test_hash()
+{
+ // Use boost::hash instead of std::hash for boost::container::string
+ boost::hash hasher;
+
+ bc::string s1("Hello");
+ bc::string s2("Hello");
+ bc::string s3("World");
+
+ BOOST_TEST_EQ(hasher(s1), hasher(s2));
+ // Different strings should (usually) have different hashes
+ BOOST_TEST(hasher(s1) != hasher(s3) || s1 == s3);
+
+ // Empty string
+ bc::string empty;
+ std::size_t h = hasher(empty);
+ use(h);
+}
+
+void test_std_swap()
+{
+ bc::string s1("Hello");
+ bc::string s2("World");
+
+ std::swap(s1, s2);
+ BOOST_TEST(s1 == "World");
+ BOOST_TEST(s2 == "Hello");
+}
+
+//==============================================================================
+// SECTION 21: Allocator awareness
+//==============================================================================
+
+void test_get_allocator()
+{
+ bc::string s("Hello");
+ auto alloc = s.get_allocator();
+
+ // Can allocate/deallocate
+ char* p = alloc.allocate(10);
+ alloc.deallocate(p, 10);
+}
+
+//==============================================================================
+// SECTION 22: Special cases and edge cases
+//==============================================================================
+
+void test_embedded_nulls()
+{
+ // String with embedded nulls
+ bc::string s("Hello\0World", 11);
+ BOOST_TEST_EQ(s.size(), 11u);
+ BOOST_TEST_EQ(s[5], '\0');
+ BOOST_TEST_EQ(s[6], 'W');
+
+ // Find with embedded null
+ BOOST_TEST_EQ(s.find('\0'), 5u);
+
+ // Substr with embedded null
+ bc::string sub = s.substr(6);
+ BOOST_TEST(sub == "World");
+
+ // Comparison with embedded nulls
+ bc::string s2("Hello\0World", 11);
+ bc::string s3("Hello\0Xorld", 11);
+ BOOST_TEST(s == s2);
+ BOOST_TEST(s != s3);
+}
+
+void test_self_operations()
+{
+ // Self-assignment
+ bc::string s("Hello");
+ s = s;
+ BOOST_TEST(s == "Hello");
+
+ // Self-append via substring
+ s = "Hello";
+ s.append(s.data(), 2);
+ BOOST_TEST(s == "HelloHe");
+
+ // Self-insert
+ s = "Hello";
+ s.insert(2, s.data(), 2);
+ BOOST_TEST(s == "HeHello");
+}
+
+void test_long_strings()
+{
+ // Test SSO boundary crossing
+ bc::string s;
+ for (int i = 0; i < 1000; ++i) {
+ s.push_back('a');
+ }
+ BOOST_TEST_EQ(s.size(), 1000u);
+ BOOST_TEST(s.capacity() >= 1000u);
+
+ // All chars should be 'a'
+ for (char c : s) {
+ BOOST_TEST_EQ(c, 'a');
+ }
+
+ // Clear and reuse
+ s.clear();
+ BOOST_TEST(s.empty());
+ s = "Hello";
+ BOOST_TEST(s == "Hello");
+}
+
+void test_move_operations()
+{
+ bc::string s1("Hello, World!");
+ bc::string s2(std::move(s1));
+ BOOST_TEST(s2 == "Hello, World!");
+
+ bc::string s3;
+ s3 = std::move(s2);
+ BOOST_TEST(s3 == "Hello, World!");
+
+ // Move-assign to self (implementation-defined, but should work)
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wself-move"
+#endif
+ s3 = std::move(s3);
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+ // s3 is in valid state
+}
+
+void test_iterator_invalidation()
+{
+ bc::string s("Hello");
+
+ // Get iterators
+ auto it = s.begin();
+ auto end = s.end();
+
+ // Operations that might invalidate
+ s.reserve(1000);
+ // Iterators may be invalid now, but string content should be same
+ BOOST_TEST(s == "Hello");
+
+ // New iterators are valid
+ BOOST_TEST_EQ(*s.begin(), 'H');
+ BOOST_TEST_EQ(s.end() - s.begin(), 5);
+
+ use(it);
+ use(end);
+}
+
+//==============================================================================
+// SECTION 23: Boost.Container specific features
+//==============================================================================
+
+// Note: nth() and index_of() are available in boost::container::vector
+// but not in boost::container::string. Testing other specific features.
+
+// Test with std::allocator (boost::container::allocator requires linking)
+void test_with_allocator()
+{
+ using string_with_alloc = bc::basic_string<
+ char,
+ std::char_traits,
+ std::allocator
+ >;
+
+ string_with_alloc s1("Hello");
+ BOOST_TEST(s1 == "Hello");
+
+ string_with_alloc s2(s1);
+ BOOST_TEST(s2 == s1);
+
+ s2 = "World";
+ BOOST_TEST(s2 == "World");
+}
+
+// Test stable growth (specific to boost::container)
+void test_growth_factor()
+{
+ bc::string s;
+ std::size_t prev_cap = s.capacity();
+
+ // Push elements and verify capacity grows
+ for (int i = 0; i < 100; ++i) {
+ s.push_back('x');
+ if (s.capacity() != prev_cap) {
+ // Capacity should grow (typically by factor > 1)
+ BOOST_TEST(s.capacity() > prev_cap);
+ prev_cap = s.capacity();
+ }
+ }
+}
+
+//==============================================================================
+// SECTION 24: Interoperability with std::string
+//==============================================================================
+
+void test_std_string_interop()
+{
+ // Construct from std::string
+ std::string std_str("Hello");
+ bc::string bc_str(std_str.begin(), std_str.end());
+ BOOST_TEST(bc_str == "Hello");
+
+ // Convert to std::string
+ std::string back(bc_str.begin(), bc_str.end());
+ BOOST_TEST(back == "Hello");
+
+ // Compare via c_str
+ BOOST_TEST_EQ(std::strcmp(bc_str.c_str(), std_str.c_str()), 0);
+}
+
+//==============================================================================
+// SECTION 25: Additional Boost.Container string methods
+//==============================================================================
+
+void test_reserve_and_shrink()
+{
+ bc::string s;
+
+ // Test reserve with exact allocation
+ s.reserve(100);
+ BOOST_TEST(s.capacity() >= 100u);
+
+ s = "Hello";
+ s.shrink_to_fit();
+ BOOST_TEST(s.capacity() >= s.size());
+}
+
+//==============================================================================
+// Main test runner
+//==============================================================================
+
+void test_with_lightweight_test()
+{
+ // Type traits
+ test_type_traits();
+
+ // Constructors
+ test_default_constructor();
+ test_allocator_constructor();
+ test_count_char_constructor();
+ test_substring_constructor();
+ test_cstring_constructor();
+ test_iterator_constructor();
+ test_copy_constructor();
+ test_move_constructor();
+ test_initializer_list_constructor();
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ test_string_view_constructor();
+#endif
+ test_default_init_constructor();
+
+ // Assignment operators
+ test_copy_assignment();
+ test_move_assignment();
+ test_cstring_assignment();
+ test_char_assignment();
+ test_initializer_list_assignment();
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ test_string_view_assignment();
+#endif
+
+ // assign() methods
+ test_assign_count_char();
+ test_assign_string();
+ test_assign_substring();
+ test_assign_move();
+ test_assign_cstring();
+ test_assign_iterators();
+ test_assign_initializer_list();
+
+ // Element access
+ test_at();
+ test_operator_bracket();
+ test_front();
+ test_back();
+ test_data();
+ test_c_str();
+#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
+ test_string_view_conversion();
+#endif
+
+ // Iterators
+ test_begin_end();
+ test_cbegin_cend();
+ test_rbegin_rend();
+ test_crbegin_crend();
+ test_iterator_arithmetic();
+
+ // Capacity
+ test_empty();
+ test_size_length();
+ test_max_size();
+ test_reserve();
+ test_capacity();
+ test_shrink_to_fit();
+
+ // Operations - clear, insert, erase
+ test_clear();
+ test_insert_char();
+ test_insert_cstring();
+ test_insert_string();
+ test_insert_iterator();
+ test_insert_initializer_list();
+ test_erase_member();
+
+ // Operations - push_back, pop_back, append
+ test_push_back();
+ test_pop_back();
+ test_append_string();
+ test_append_cstring();
+ test_append_char();
+ test_append_iterators();
+ test_append_initializer_list();
+ test_operator_plus_equals();
+
+ // Operations - compare
+ test_compare();
+
+ // Operations - starts_with, ends_with, contains
+ test_starts_with();
+ test_ends_with();
+ test_contains();
+
+ // Operations - replace
+ test_replace_pos();
+ test_replace_iterator();
+
+ // Operations - substr
+ test_substr();
+
+ // Operations - copy
+ test_copy();
+
+ // Operations - resize
+ test_resize();
+ test_resize_default_init();
+
+ // Operations - swap
+ test_swap();
+
+ // Search operations
+ test_find();
+ test_rfind();
+ test_find_first_of();
+ test_find_last_of();
+ test_find_first_not_of();
+ test_find_last_not_of();
+
+ // Non-member operators
+ test_concatenation_operator();
+ test_comparison_operators();
+
+ // I/O
+ test_stream_output();
+ test_stream_input();
+ test_getline();
+
+ // Hash and utilities
+ test_hash();
+ test_std_swap();
+
+ // Allocator
+ test_get_allocator();
+
+ // Special cases
+ test_embedded_nulls();
+ test_self_operations();
+ test_long_strings();
+ test_move_operations();
+ test_iterator_invalidation();
+
+ // Boost.Container specific
+ test_with_allocator();
+ test_growth_factor();
+
+ // Interoperability
+ test_std_string_interop();
+ test_reserve_and_shrink();
+}
+*/
int main()
{
if(string_test()){
@@ -607,5 +2505,7 @@ int main()
"has_trivial_destructor_after_move(std::allocator) test failed");
}
+ //test_with_lightweight_test();
+
return boost::report_errors();
}