From: Yuao Ma Date: Tue, 2 Dec 2025 15:35:40 +0000 (+0800) Subject: libstdc++: implement P3044R2 - sub-string_view from string (string part) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6123cb8bfc39323e0c175dd374e6dfe9b2984ee7;p=thirdparty%2Fgcc.git libstdc++: implement P3044R2 - sub-string_view from string (string part) 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. --- diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index c4b6b1064a94..b1db722402f2 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/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index f9df2be20bed..e59897eef49d 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -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. diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 97ded057a87b..918b4158b475 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 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 000000000000..c384948cc520 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/char.cc @@ -0,0 +1,46 @@ +// { dg-do run { target c++26 } } + +#include +#include +#include +#include + +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 000000000000..3b8e6a87fe60 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/subview/wchar_t.cc @@ -0,0 +1,46 @@ +// { dg-do run { target c++26 } } + +#include +#include +#include +#include + +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; +}