On Sat, Nov 22, 2025 at 12:41 AM Jonathan Wakely <[email protected]> wrote: > > On Fri, 21 Nov 2025 at 16:32, Yuao Ma <[email protected]> wrote: > > > > On Fri, Nov 21, 2025 at 7:52 PM Jonathan Wakely <[email protected]> wrote: > > > > > > On Thu, 20 Nov 2025 at 17:51, Yuao Ma <[email protected]> wrote: > > > > > > > > Hi all, > > > > > > > > This patch implements P3044R2 by adding a subview function for string > > > > and string_view. The implementation delegates directly to substr. > > > > Tested on x86_64-linux. > > > > > > The new basic_string::subview member needs to be added to > > > include/bits/cow_string.h as well, or the new tests need to be > > > disabled for the old COW std::string ABI. > > > > > > > The nodiscard and Markdown symbols are fixed. I also added the > > Thanks! > > > cxx11_abi effective target to the tests, since we likely don't want to > > use the COW ABI with C++26. > > You would be surprised, people still do use it! > > If the feature is absent for the COW string then bits/version.def > needs to use cxx11abi = yes so that the new macro is not defined for > the COW ABI. >
Got it! Fixed in the new series.
From 668363e4dbf6db6d7cd40899a480256936dcd0ae Mon Sep 17 00:00:00 2001 From: Yuao Ma <[email protected]> Date: Sat, 22 Nov 2025 00:37:48 +0800 Subject: [PATCH 1/2] libstdc++: implement P3044R2 - sub-string_view from string (string_view part) libstdc++-v3/ChangeLog: * include/bits/version.def: Add string_subview FTM. * include/bits/version.h: Regenerate. * include/std/string_view: Add subview. * testsuite/21_strings/basic_string_view/operations/subview/char.cc: New test. * testsuite/21_strings/basic_string_view/operations/subview/wchar_t.cc: New test. --- libstdc++-v3/include/bits/version.def | 9 ++++ libstdc++-v3/include/bits/version.h | 10 ++++ libstdc++-v3/include/std/string_view | 10 +++- .../operations/subview/char.cc | 52 +++++++++++++++++++ .../operations/subview/wchar_t.cc | 52 +++++++++++++++++++ 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/char.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/wchar_t.cc diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 29ecf15c7e3..b5575d2399f 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1934,6 +1934,15 @@ ftms = { }; }; +ftms = { + name = string_subview; + values = { + v = 202506; + cxxmin = 26; + hosted = yes; + }; +}; + ftms = { name = to_underlying; values = { diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 5901d27113d..413da56b088 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2161,6 +2161,16 @@ #endif /* !defined(__cpp_lib_string_resize_and_overwrite) */ #undef __glibcxx_want_string_resize_and_overwrite +#if !defined(__cpp_lib_string_subview) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_string_subview 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_subview) +# define __cpp_lib_string_subview 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_string_subview) */ +#undef __glibcxx_want_string_subview + #if !defined(__cpp_lib_to_underlying) # if (__cplusplus >= 202100L) # define __glibcxx_to_underlying 202102L diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 842f6ad89af..b226544fa6f 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -40,9 +40,10 @@ #define __glibcxx_want_constexpr_char_traits #define __glibcxx_want_constexpr_string_view #define __glibcxx_want_freestanding_string_view -#define __glibcxx_want_string_view #define __glibcxx_want_starts_ends_with #define __glibcxx_want_string_contains +#define __glibcxx_want_string_subview +#define __glibcxx_want_string_view #include <bits/version.h> #if __cplusplus >= 201703L @@ -342,6 +343,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return basic_string_view{_M_str + __pos, __rlen}; } +#ifdef __glibcxx_string_subview // >= C++26 + [[nodiscard]] + constexpr basic_string_view + subview(size_type __pos = 0, size_type __n = npos) const + { return substr(__pos, __n); } +#endif + [[nodiscard]] constexpr int compare(basic_string_view __str) const noexcept diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/char.cc new file mode 100644 index 00000000000..296d85af69b --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/char.cc @@ -0,0 +1,52 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target cxx11_abi } + +#include <string_view> +#include <testsuite_hooks.h> + +#if __STDC_HOSTED__ +#include <stdexcept> +#endif + +void test01() { + typedef std::string_view::size_type csize_type; + typedef std::string_view::const_reference cref; + typedef std::string_view::reference ref; + csize_type csz01; + + const char str_lit01[] = "rockaway, pacifica"; + const std::string_view str01(str_lit01); + std::string_view str02; + + csz01 = str01.size(); + str02 = str01.subview(0, 1); + VERIFY(str02 == "r"); + str02 = str01.subview(10); + VERIFY(str02 == "pacifica"); + +#if __STDC_HOSTED__ + try { + str02 = str01.subview(csz01 + 1); + VERIFY(false); + } catch (std::out_of_range &fail) { + VERIFY(true); + } catch (...) { + VERIFY(false); + } + + try { + str02 = str01.subview(csz01); + VERIFY(str02.size() == 0); + VERIFY(str02.begin() == str01.end()); + VERIFY(true); + } catch (...) { + VERIFY(false); + } +#endif // HOSTED +} + +int main() { + test01(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/wchar_t.cc new file mode 100644 index 00000000000..461d1005c65 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/subview/wchar_t.cc @@ -0,0 +1,52 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target cxx11_abi } + +#include <string_view> +#include <testsuite_hooks.h> + +#if __STDC_HOSTED__ +#include <stdexcept> +#endif + +void test01() { + typedef std::wstring_view::size_type csize_type; + typedef std::wstring_view::const_reference cref; + typedef std::wstring_view::reference ref; + csize_type csz01; + + const wchar_t str_lit01[] = L"rockaway, pacifica"; + const std::wstring_view str01(str_lit01); + std::wstring_view str02; + + csz01 = str01.size(); + str02 = str01.subview(0, 1); + VERIFY(str02 == L"r"); + str02 = str01.subview(10); + VERIFY(str02 == L"pacifica"); + +#if __STDC_HOSTED__ + try { + str02 = str01.subview(csz01 + 1); + VERIFY(false); + } catch (std::out_of_range &fail) { + VERIFY(true); + } catch (...) { + VERIFY(false); + } + + try { + str02 = str01.subview(csz01); + VERIFY(str02.size() == 0); + VERIFY(str02.begin() == str01.end()); + VERIFY(true); + } catch (...) { + VERIFY(false); + } +#endif // HOSTED +} + +int main() { + test01(); + + return 0; +} -- 2.51.1
From 6aa79695876a6834d0a009a68df864998a3f7056 Mon Sep 17 00:00:00 2001 From: Yuao Ma <[email protected]> Date: Sat, 22 Nov 2025 00:38:54 +0800 Subject: [PATCH 2/2] libstdc++: implement P3044R2 - sub-string_view from string (string part) libstdc++-v3/ChangeLog: * include/bits/basic_string.h: Add subview. * include/std/string: Add FTM. * testsuite/21_strings/basic_string/operations/subview/char.cc: New test. * testsuite/21_strings/basic_string/operations/subview/wchar_t.cc: New test. --- libstdc++-v3/include/bits/basic_string.h | 19 ++++++++ libstdc++-v3/include/std/string | 1 + .../basic_string/operations/subview/char.cc | 47 +++++++++++++++++++ .../operations/subview/wchar_t.cc | 47 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index c4b6b1064a9..b1db722402f 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3442,6 +3442,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return basic_string(*this, _M_check(__pos, "basic_string::substr"), __n); } +#ifdef __glibcxx_string_subview // >= C++26 + /** + * @brief Get a subview. + * @param __pos Index of first character (default 0). + * @param __n Number of characters in subview (default remainder). + * @return The subview. + * @throw std::out_of_range If __pos > size(). + * + * Construct and return a subview using the `__n` characters starting at + * `__pos`. If the string is too short, use the remainder of the + * characters. If `__pos` is beyond the end of the string, out_of_range + * is thrown. + */ + [[nodiscard]] + constexpr basic_string_view<_CharT, _Traits> + subview(size_type __pos = 0, size_type __n = npos) const + { return __sv_type(*this).subview(__pos, __n); } +#endif + /** * @brief Compare to a string. * @param __str String to compare against. diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 97ded057a87..918b4158b47 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -63,6 +63,7 @@ #define __glibcxx_want_erase_if #define __glibcxx_want_nonmember_container_access #define __glibcxx_want_string_resize_and_overwrite +#define __glibcxx_want_string_subview #define __glibcxx_want_string_udls #define __glibcxx_want_to_string #include <bits/version.h> diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc new file mode 100644 index 00000000000..da541f2c9f8 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc @@ -0,0 +1,47 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target cxx11_abi } + +#include <stdexcept> +#include <string> +#include <string_view> +#include <testsuite_hooks.h> + +void test01(void) { + typedef std::string::size_type csize_type; + typedef std::string::const_reference cref; + typedef std::string::reference ref; + csize_type csz01; + + const char str_lit01[] = "rockaway, pacifica"; + const std::string str01(str_lit01); + std::string_view str02; + + csz01 = str01.size(); + str02 = str01.subview(0, 1); + VERIFY(str02 == "r"); + str02 = str01.subview(10); + VERIFY(str02 == "pacifica"); + + try { + str02 = str01.subview(csz01 + 1); + VERIFY(false); + } catch (std::out_of_range &fail) { + VERIFY(true); + } catch (...) { + VERIFY(false); + } + + try { + str02 = str01.subview(csz01); + VERIFY(str02.size() == 0); + } catch (std::out_of_range &fail) { + VERIFY(false); + } catch (...) { + VERIFY(false); + } +} + +int main() { + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc new file mode 100644 index 00000000000..06025a0b638 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc @@ -0,0 +1,47 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target cxx11_abi } + +#include <stdexcept> +#include <string> +#include <string_view> +#include <testsuite_hooks.h> + +void test01(void) { + typedef std::wstring::size_type csize_type; + typedef std::wstring::const_reference cref; + typedef std::wstring::reference ref; + csize_type csz01; + + const wchar_t str_lit01[] = L"rockaway, pacifica"; + const std::wstring str01(str_lit01); + std::wstring_view str02; + + csz01 = str01.size(); + str02 = str01.subview(0, 1); + VERIFY(str02 == L"r"); + str02 = str01.subview(10); + VERIFY(str02 == L"pacifica"); + + try { + str02 = str01.subview(csz01 + 1); + VERIFY(false); + } catch (std::out_of_range &fail) { + VERIFY(true); + } catch (...) { + VERIFY(false); + } + + try { + str02 = str01.subview(csz01); + VERIFY(str02.size() == 0); + } catch (std::out_of_range &fail) { + VERIFY(false); + } catch (...) { + VERIFY(false); + } +} + +int main() { + test01(); + return 0; +} -- 2.51.1
