-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[libc++][string] P3044R2: sub-string_view
from string
#147095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
H-G-Hristov
wants to merge
19
commits into
llvm:main
Choose a base branch
from
H-G-Hristov:hgh/libcxx/P3044R2-sub-string_view-from-string
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
[libc++][string] P3044R2: sub-string_view
from string
#147095
H-G-Hristov
wants to merge
19
commits into
llvm:main
from
H-G-Hristov:hgh/libcxx/P3044R2-sub-string_view-from-string
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-libcxx Author: Hristo Hristov (H-G-Hristov) ChangesImplements P3044R2 Note: ReferencesFull diff: https://github.com/llvm/llvm-project/pull/147095.diff 5 Files Affected:
diff --git a/libcxx/include/string b/libcxx/include/string
index c450ddcb41914..9476c3df3b8e7 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -280,6 +280,8 @@ public:
basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr in C++20, removed in C++23
basic_string substr(size_type pos = 0, size_type n = npos) const&; // since C++23
constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; // since C++23
+ constexpr basic_string_view<charT, traits> subview(size_type pos = 0,
+ size_type n = npos) const; // since C++26
void swap(basic_string& str)
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20
@@ -1745,6 +1747,13 @@ public:
}
# endif
+# if _LIBCPP_STD_VER >= 26
+ _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT, _Traits>
+ subview(size_type __pos = 0, size_type __n = npos) const {
+ return basic_string_view<_CharT, _Traits>(*this).subview(__pos, __n);
+ }
+# endif
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str)
# if _LIBCPP_STD_VER >= 14
_NOEXCEPT;
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 861187c0640e1..ad036882e1630 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -130,6 +130,8 @@ namespace std {
size_type copy(charT* s, size_type n, size_type pos = 0) const; // constexpr in C++20
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
+ constexpr basic_string_view subview(size_type pos = 0,
+ size_type n = npos) const; // freestanding-deleted, since C++26
constexpr int compare(basic_string_view s) const noexcept;
constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
constexpr int compare(size_type pos1, size_type n1,
@@ -465,6 +467,12 @@ public:
: basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
}
+# if _LIBCPP_STD_VER >= 26
+ _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
+ return this->substr(__pos, __n);
+ }
+# endif
+
_LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
size_type __rlen = std::min(size(), __sv.size());
int __retval = _Traits::compare(data(), __sv.data(), __rlen);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
new file mode 100644
index 0000000000000..65418dcb4d7be
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <string>
+
+// constexpr basic_string_view<_CharT, _Traits> subview(size_type __pos = 0, size_type __n = npos) const;
+
+#include <cassert>
+#include <string>
+
+constexpr bool test() {
+ std::string s{"Hello cruel world!"};
+ auto sub = s.subview(6);
+ assert(sub == "cruel world!");
+ auto subsub = sub.subview(0, 5);
+ assert(subsub == "cruel");
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
index 62b0259c175f8..02755985ead70 100644
--- a/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
+++ b/libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
@@ -11,6 +11,10 @@
// <string_view>
// constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
+// constexpr basic_string_view subview(size_type pos = 0,
+// size_type n = npos) const; // freestanding-deleted
+
+// subview is alternative name of substr
// Throws: out_of_range if pos > size().
// Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
@@ -25,15 +29,21 @@
#include "test_macros.h"
template <typename CharT>
-void test1(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
+struct Test {
+ typedef std::basic_string_view<CharT> (std::basic_string_view<CharT>::*Sub)(
+ typename std::basic_string_view<CharT>::size_type, typename std::basic_string_view<CharT>::size_type) const;
+};
+
+template <typename CharT, typename Test<CharT>::Sub TestSub>
+void testDetail(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
std::basic_string_view<CharT> sv1;
#ifdef TEST_HAS_NO_EXCEPTIONS
if (pos > sv.size())
return; // would throw if exceptions were enabled
- sv1 = sv.substr(pos, n);
+ sv1 = (sv.*TestSub)(pos, n);
#else
try {
- sv1 = sv.substr(pos, n);
+ sv1 = (sv.*TestSub)(pos, n);
assert(pos <= sv.size());
} catch (const std::out_of_range&) {
assert(pos > sv.size());
@@ -46,79 +56,101 @@ void test1(std::basic_string_view<CharT> sv, std::size_t n, size_t pos) {
assert(sv[pos + i] == sv1[i]);
}
-template <typename CharT>
-void test(const CharT* s) {
- typedef std::basic_string_view<CharT> string_view_t;
+template <typename CharT, typename Test<CharT>::Sub TestSub>
+void testCases(const CharT* s) {
+ std::basic_string_view<CharT> sv(s);
- string_view_t sv1(s);
+ testDetail<CharT, TestSub>(sv, 0, 0);
+ testDetail<CharT, TestSub>(sv, 1, 0);
+ testDetail<CharT, TestSub>(sv, 20, 0);
+ testDetail<CharT, TestSub>(sv, sv.size(), 0);
- test1(sv1, 0, 0);
- test1(sv1, 1, 0);
- test1(sv1, 20, 0);
- test1(sv1, sv1.size(), 0);
+ testDetail<CharT, TestSub>(sv, 100, 3);
- test1(sv1, 0, 3);
- test1(sv1, 2, 3);
- test1(sv1, 100, 3);
+ testDetail<CharT, TestSub>(sv, 0, std::basic_string_view<CharT>::npos);
+ testDetail<CharT, TestSub>(sv, 2, std::basic_string_view<CharT>::npos);
+ testDetail<CharT, TestSub>(sv, sv.size(), std::basic_string_view<CharT>::npos);
- test1(sv1, 0, string_view_t::npos);
- test1(sv1, 2, string_view_t::npos);
- test1(sv1, sv1.size(), string_view_t::npos);
+ testDetail<CharT, TestSub>(sv, sv.size() + 1, 0);
+ testDetail<CharT, TestSub>(sv, sv.size() + 1, 1);
+ testDetail<CharT, TestSub>(sv, sv.size() + 1, std::basic_string_view<CharT>::npos);
+}
- test1(sv1, sv1.size() + 1, 0);
- test1(sv1, sv1.size() + 1, 1);
- test1(sv1, sv1.size() + 1, string_view_t::npos);
+template <typename CharT>
+void testSubs(const CharT* s) {
+ testCases<CharT, &std::basic_string_view<CharT>::substr>(s);
+#if TEST_STD_VER >= 26
+ testCases<CharT, &std::basic_string_view<CharT>::subview>(s);
+#endif // TEST_STD_VER >= 26
}
-int main(int, char**) {
- test("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
- test("ABCDE");
- test("a");
- test("");
+void test() {
+ testSubs("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+ testSubs("ABCDE");
+ testSubs("a");
+ testSubs("");
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
- test(L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
- test(L"ABCDE");
- test(L"a");
- test(L"");
+ testSubs(
+ L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+ testSubs(L"ABCDE");
+ testSubs(L"a");
+ testSubs(L"");
#endif
#if TEST_STD_VER >= 11
- test(u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
- test(u"ABCDE");
- test(u"a");
- test(u"");
-
- test(U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
- test(U"ABCDE");
- test(U"a");
- test(U"");
+ testSubs(
+ u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+ testSubs(u"ABCDE");
+ testSubs(u"a");
+ testSubs(u"");
+
+ testSubs(
+ U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
+ testSubs(U"ABCDE");
+ testSubs(U"a");
+ testSubs(U"");
#endif
+}
+
+#if TEST_STD_VER >= 14
+template <typename Test<char>::Sub TestSub>
+constexpr void testConstexprDetail() {
+ constexpr std::string_view sv{"ABCDE", 5};
+ {
+ constexpr std::string_view sv2 = (sv.*TestSub)(0, 3);
+
+ static_assert(sv2.size() == 3, "");
+ static_assert(sv2[0] == 'A', "");
+ static_assert(sv2[1] == 'B', "");
+ static_assert(sv2[2] == 'C', "");
+ }
-#if TEST_STD_VER > 11
{
- constexpr std::string_view sv1{"ABCDE", 5};
-
- {
- constexpr std::string_view sv2 = sv1.substr(0, 3);
- static_assert(sv2.size() == 3, "");
- static_assert(sv2[0] == 'A', "");
- static_assert(sv2[1] == 'B', "");
- static_assert(sv2[2] == 'C', "");
- }
-
- {
- constexpr std::string_view sv2 = sv1.substr(3, 0);
- static_assert(sv2.size() == 0, "");
- }
-
- {
- constexpr std::string_view sv2 = sv1.substr(3, 3);
- static_assert(sv2.size() == 2, "");
- static_assert(sv2[0] == 'D', "");
- static_assert(sv2[1] == 'E', "");
- }
+ constexpr std::string_view sv2 = (sv.*TestSub)(3, 0);
+ static_assert(sv2.size() == 0, "");
}
+
+ {
+ constexpr std::string_view sv2 = (sv.*TestSub)(3, 3);
+ static_assert(sv2.size() == 2, "");
+ static_assert(sv2[0] == 'D', "");
+ static_assert(sv2[1] == 'E', "");
+ }
+}
+
+void test_constexpr() {
+ testConstexprDetail<&std::string_view::substr>();
+# if TEST_STD_VER >= 26
+ testConstexprDetail<&std::string_view::subview>();
+# endif
+}
+#endif
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 14
+ test_constexpr();
#endif
return 0;
diff --git a/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
new file mode 100644
index 0000000000000..fec258eef4546
--- /dev/null
+++ b/libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <string_view>
+
+// constexpr basic_string_view subview(size_type pos = 0,
+// size_type n = npos) const; // freestanding-deleted
+
+int main(int, char**) {
+ // This test is intentionally empty because subview is an alias for substr
+ // and is tested in substr.pass.cpp.
+ return 0;
+}
|
libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
Outdated
Show resolved
Hide resolved
582e674
to
ad5e410
Compare
string_view
from string
string_view
from string
ldionne
reviewed
Aug 1, 2025
libcxx/test/std/strings/basic.string/string.ops/string_substr/subview.pass.cpp
Show resolved
Hide resolved
libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp
Outdated
Show resolved
Hide resolved
…s://github.com/H-G-Hristov/llvm-project into hgh/libcxx/P3044R2-sub-string_view-from-string
✅ With the latest revision this PR passed the C/C++ code formatter. |
H-G-Hristov
commented
Aug 6, 2025
libcxx/test/std/strings/string.view/string.view.ops/subview.pass.cpp
Outdated
Show resolved
Hide resolved
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implements P3044R2
Note:
substr.pass.cpp
is refactored to accommodate the test ofbasic_string_view
'ssubview
which is an alias ofsubstr
without changing the test cases.Closes #148140
References