[PATCH] libstdc++: implement P3044R2 - sub-string_view from string
Patrick Palka
ppalka@redhat.com
Mon Dec 1 19:27:04 GMT 2025
On Sat, 22 Nov 2025, Yuao Ma wrote:
> On Sat, Nov 22, 2025 at 12:33 AM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
> >
> >
> >
> > On Fri, Nov 21, 2025 at 5:11 PM Yuao Ma <addr2line@gmail.com> wrote:
> >>
> >> On Fri, Nov 21, 2025 at 6:32 PM Tomasz Kaminski <tkaminsk@redhat.com> 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 <c8ef@outlook.com>
> 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
>
More information about the Libstdc++
mailing list