diff options
| author | Jonathan Wakely <jwakely@redhat.com> | 2025-04-10 13:40:53 +0100 |
|---|---|---|
| committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-04-11 11:18:30 +0100 |
| commit | 882d3b319dbf50ae64080731a1398031c100b7c7 (patch) | |
| tree | 709dcbc0553cc9935f3090e292ad7f0dea2d2163 /libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append | |
| parent | 3b33d792cf1e4d2ea3d36d3ad403cbb452243cd8 (diff) | |
libstdc++: Add P1206R7 from_range members to std::string [PR111055]
This is the last piece of P1206R7, adding new members to
std::basic_string.
libstdc++-v3/ChangeLog:
PR libstdc++/111055
* include/bits/basic_string.h (_S_copy_range): New function.
(basic_string(from_range_t, R%%, const Alloc&)): New
constructor.
(append_range, assign_range, insert_range, replace_with_range):
New functions.
* include/bits/cow_string.h: Likewise.
* testsuite/21_strings/basic_string/cons/from_range.cc: New
test.
* testsuite/21_strings/basic_string/modifiers/append/append_range.cc:
New test.
* testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc:
New test.
* testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc:
New test.
* testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc:
New test.
Co-authored-by: Tomasz KamiĆski <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append')
| -rw-r--r-- | libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc new file mode 100644 index 00000000000..6c0bc0cab18 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc @@ -0,0 +1,125 @@ +// { dg-do run { target c++23 } } + +#include <span> +#include <string> +#include <testsuite_allocator.h> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +template<typename Range, typename Alloc> +constexpr void +do_test() +{ + // The vector's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + using CT = std::char_traits<V>; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}; + + auto eq = [](const std::basic_string<V, CT, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + Range r4(a, a+4); + Range r5(a+4, a+9); + Range r11(a+9, a+20); + + std::basic_string<V, CT, Alloc> v; + v.append_range(r4); + VERIFY( eq(v, {a, 4}) ); + v.append_range(r5); + VERIFY( eq(v, {a, 9}) ); + + std::basic_string<V, CT, Alloc> const s = v; + v.append_range(r11); + VERIFY( eq(v, a) ); + v.append_range(Range(a, a)); + VERIFY( eq(v, a) ); + v.clear(); + v.append_range(Range(a, a)); + VERIFY( v.empty() ); +} + +template<typename Range> +void +do_test_a() +{ + do_test<Range, std::allocator<char>>(); + do_test<Range, __gnu_test::SimpleAllocator<char>>(); + do_test<Range, std::allocator<wchar_t>>(); + do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>(); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<char>>(); + do_test_a<test_forward_sized_range<char>>(); + do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<char>>(); + do_test_a<test_input_sized_range<char>>(); + do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>(); + + do_test_a<test_range<char, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>(); + + // Not lvalue-convertible to char + struct C { + C(char v) : val(v) { } + operator char() && { return val; } + bool operator==(char b) const { return b == val; } + char val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range, std::allocator<char>>(); + + return true; +} + +void +test_overlapping() +{ + std::string const s = "1234abcd"; + + std::string c = s; + c.append_range(std::string_view(c)); + VERIFY( c == "1234abcd1234abcd" ); + + c = s; + c.append_range(std::string_view(c).substr(4, 4)); + VERIFY( c == "1234abcdabcd" ); + + c = s; + c.reserve(12); + c.append_range(std::string_view(c).substr(0, 4)); + VERIFY( c == "1234abcd1234" ); +} + +constexpr bool +test_constexpr() +{ +#if _GLIBCXX_USE_CXX11_ABI + // XXX: this doesn't test the non-forward_range code paths are constexpr. + do_test<std::string_view, std::allocator<char>>(); +#endif // _GLIBCXX_USE_CXX11_ABI + return true; +} + +int main() +{ + test_ranges(); + test_overlapping(); + static_assert( test_constexpr() ); +} |
