]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: implement P3044R2 - sub-string_view from string (string part)
authorYuao Ma <c8ef@outlook.com>
Tue, 2 Dec 2025 15:35:40 +0000 (23:35 +0800)
committerYuao Ma <c8ef@outlook.com>
Wed, 3 Dec 2025 15:56:32 +0000 (23:56 +0800)
libstdc++-v3/ChangeLog:

* include/bits/basic_string.h: Add subview.
* include/bits/cow_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
libstdc++-v3/include/bits/cow_string.h
libstdc++-v3/include/std/string
libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc [new file with mode: 0644]

index c4b6b1064a94d0f2be5b3d90c5dfb0b0ae6f22df..b1db722402f2c08b5f13aefe2ba8a6ff182531a0 100644 (file)
@@ -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.
index f9df2be20bed292747f0b89e5634baa1d3b6f366..e59897eef49d5015cf06966b3527ec39f41ebead 100644 (file)
@@ -2919,6 +2919,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { 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.
index 97ded057a87b44553d91965cfc982571d9776a7c..918b4158b47531ca46e6925edb0c507b1a82b539 100644 (file)
@@ -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 (file)
index 0000000..c384948
--- /dev/null
@@ -0,0 +1,46 @@
+// { dg-do run { target c++26 } }
+
+#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 (file)
index 0000000..3b8e6a8
--- /dev/null
@@ -0,0 +1,46 @@
+// { dg-do run { target c++26 } }
+
+#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;
+}