On Sat, 22 Nov 2025, Yuao Ma wrote: > On Sat, Nov 22, 2025 at 12:33 AM Tomasz Kaminski <[email protected]> wrote: > > > > > > > > On Fri, Nov 21, 2025 at 5:11 PM Yuao Ma <[email protected]> wrote: > >> > >> On Fri, Nov 21, 2025 at 6:32 PM Tomasz Kaminski <[email protected]> > >> wrote: > >> > > >> > There was a paper submitted before Kona: p3862r0 Postpone > >> > basic_string::subview and wait for cstring_view [1], > >> > that according to github papers status [2] have also NB comment. I was > >> > not able to locale the comment thou. > >> > So maybe it would be good to have this as patch series for string_view > >> > (that would contain feature test macro) and then string, > >> > so we can revert later? > >> > > >> > > >> > [1] > >> > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3862r0.html# > >> > [2] https://github.com/cplusplus/papers/issues/2466 > >> > > >> > >> Thanks for the info! Could you elaborate more on how making this a > >> patch series helps with reverting? My understanding of P3862R0 is that > >> it proposed two wording options: one to entirely remove the subview > >> for string and string_view, and the other to remove the default > >> parameter argument. > > > > Both wording options are changing only basic_string::subview, > > and not touching subview on string_view at all. > > Oh yeah, my mistake. Split into two patches as below.
> 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; I think we need to add cxx11abi = yes if we don't support this with the COW string. Wouldn't adding COW string support amount to a few extra lines in cow_string.h though? > + }; > +}; > + > 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 IIUC since subview is specified as freestanding-deleted, we need to define it as deleted if we don't support it in freestanding mode. So perhaps why don't we just always define it in C++26 mode regardless of whether the FTM is defined? Maybe I'm not understanding the intent of freestanding-deleted though. > + > [[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 >
