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.
This commit is contained in:
Yuao Ma 2025-12-02 23:35:40 +08:00
parent 475933164f
commit 6123cb8bfc
5 changed files with 131 additions and 0 deletions

View 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.

View 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.

View 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>

View File

@ -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;
}

View File

@ -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;
}