-
Notifications
You must be signed in to change notification settings - Fork 14.4k
WIP [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
base: main
Are you sure you want to change the base?
WIP [libc++][string] P3044R2: sub-string_view
from string
#147095
Conversation
@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;
+}
|
// This test is intentionally empty because subview is an alias for substr | ||
// and is tested in substr.pass.cpp. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't need this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure what the current practice about function aliases is. Normally we want a test file per function. This one is to tell the user what to look at. Are there any similar cases in the library?
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.References