Skip to content

Commit 0510c78

Browse files
committed
WIP [libc++][string] P3044R2: sub-string_view from string
Implements [P3044R2](https://wg21.link/P3044R2) - cplusplus/draft#7975
1 parent 9f733f4 commit 0510c78

File tree

5 files changed

+208
-125
lines changed

5 files changed

+208
-125
lines changed

libcxx/include/string

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ public:
280280
basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr in C++20, removed in C++23
281281
basic_string substr(size_type pos = 0, size_type n = npos) const&; // since C++23
282282
constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; // since C++23
283+
constexpr basic_string_view<charT, traits> subview(size_type pos = 0,
284+
size_type n = npos) const; // since C++26
283285
void swap(basic_string& str)
284286
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
285287
allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20
@@ -1752,6 +1754,13 @@ public:
17521754
}
17531755
# endif
17541756

1757+
# if _LIBCPP_STD_VER >= 26
1758+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT, _Traits>
1759+
subview(size_type __pos = 0, size_type __n = npos) const {
1760+
return basic_string_view<_CharT, _Traits>(*this).subview(__pos, __n);
1761+
}
1762+
# endif
1763+
17551764
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str)
17561765
# if _LIBCPP_STD_VER >= 14
17571766
_NOEXCEPT;

libcxx/include/string_view

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ namespace std {
130130
size_type copy(charT* s, size_type n, size_type pos = 0) const; // constexpr in C++20
131131
132132
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
133+
constexpr basic_string_view subview(size_type pos = 0,
134+
size_type n = npos) const; // freestanding-deleted, since C++26
133135
constexpr int compare(basic_string_view s) const noexcept;
134136
constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
135137
constexpr int compare(size_type pos1, size_type n1,
@@ -465,6 +467,12 @@ public:
465467
: basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
466468
}
467469

470+
# if _LIBCPP_STD_VER >= 26
471+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string_view subview(size_type __pos = 0, size_type __n = npos) const {
472+
return this->substr(__pos, __n);
473+
}
474+
# endif
475+
468476
_LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
469477
size_type __rlen = std::min(size(), __sv.size());
470478
int __retval = _Traits::compare(data(), __sv.data(), __rlen);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++26
10+
11+
// <string>
12+
13+
// constexpr basic_string_view<_CharT, _Traits> subview(size_type __pos = 0, size_type __n = npos) const;
14+
15+
#include <cassert>
16+
#include <string>
17+
18+
constexpr bool test() {
19+
std::string s{"Hello cruel world!"};
20+
auto sub = s.subview(6);
21+
assert(sub == "cruel world!");
22+
auto subsub = sub.subview(0, 5);
23+
assert(subsub == "cruel");
24+
25+
return true;
26+
}
27+
28+
int main(int, char**) {
29+
test();
30+
static_assert(test());
31+
32+
return 0;
33+
}

libcxx/test/std/strings/string.view/string.view.ops/substr.pass.cpp

Lines changed: 0 additions & 125 deletions
This file was deleted.
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: !stdlib=libc++ && (c++03 || c++11 || c++14)
10+
11+
// <string_view>
12+
13+
// constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
14+
// constexpr basic_string_view subview(size_type pos = 0,
15+
// size_type n = npos) const; // freestanding-deleted
16+
17+
// subview is alternative name of substr
18+
19+
// Throws: out_of_range if pos > size().
20+
// Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
21+
// Returns: basic_string_view(data()+pos, rlen).
22+
23+
#include <algorithm>
24+
#include <cassert>
25+
#include <cstddef>
26+
#include <stdexcept>
27+
#include <string_view>
28+
29+
#include "test_macros.h"
30+
31+
template <typename CharT>
32+
struct Test {
33+
typedef std::basic_string_view<CharT> (std::basic_string_view<CharT>::*Sub)(
34+
typename std::basic_string_view<CharT>::size_type, typename std::basic_string_view<CharT>::size_type) const;
35+
};
36+
37+
template <typename CharT>
38+
void testDetail(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub, std::size_t n, size_t pos) {
39+
(void)testSub; // Avoid unused parameter warning
40+
std::basic_string_view<CharT> sv1;
41+
#ifdef TEST_HAS_NO_EXCEPTIONS
42+
if (pos > sv.size())
43+
return; // would throw if exceptions were enabled
44+
sv1 = (sv.*testSub)(pos, n);
45+
#else
46+
try {
47+
sv1 = (sv.*testSub)(pos, n);
48+
assert(pos <= sv.size());
49+
} catch (const std::out_of_range&) {
50+
assert(pos > sv.size());
51+
return;
52+
}
53+
#endif
54+
const std::size_t rlen = std::min(n, sv.size() - pos);
55+
assert(sv1.size() == rlen);
56+
for (std::size_t i = 0; i < rlen; ++i)
57+
assert(sv[pos + i] == sv1[i]);
58+
}
59+
60+
template <typename CharT>
61+
void testCases(std::basic_string_view<CharT> sv, typename Test<CharT>::Sub testSub) {
62+
testDetail(sv, testSub, 0, 0);
63+
testDetail(sv, testSub, 1, 0);
64+
testDetail(sv, testSub, 20, 0);
65+
testDetail(sv, testSub, sv.size(), 0);
66+
67+
testDetail(sv, testSub, 100, 3);
68+
69+
testDetail(sv, testSub, 0, std::basic_string_view<CharT>::npos);
70+
testDetail(sv, testSub, 2, std::basic_string_view<CharT>::npos);
71+
testDetail(sv, testSub, sv.size(), std::basic_string_view<CharT>::npos);
72+
73+
testDetail(sv, testSub, sv.size() + 1, 0);
74+
testDetail(sv, testSub, sv.size() + 1, 1);
75+
testDetail(sv, testSub, sv.size() + 1, std::basic_string_view<CharT>::npos);
76+
}
77+
78+
template <typename CharT>
79+
void testSubs(const CharT* s) {
80+
std::basic_string_view<CharT> sv(s);
81+
82+
testCases(sv, &std::basic_string_view<CharT>::substr);
83+
#if TEST_STD_VER >= 26
84+
testCases(sv, &std::basic_string_view<CharT>::subview);
85+
#endif // TEST_STD_VER >= 26
86+
}
87+
88+
void test() {
89+
testSubs("ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
90+
testSubs("ABCDE");
91+
testSubs("a");
92+
testSubs("");
93+
94+
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
95+
testSubs(
96+
L"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
97+
testSubs(L"ABCDE");
98+
testSubs(L"a");
99+
testSubs(L"");
100+
#endif
101+
102+
#if TEST_STD_VER >= 11
103+
testSubs(
104+
u"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
105+
testSubs(u"ABCDE");
106+
testSubs(u"a");
107+
testSubs(u"");
108+
109+
testSubs(
110+
U"ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDE");
111+
testSubs(U"ABCDE");
112+
testSubs(U"a");
113+
testSubs(U"");
114+
#endif
115+
}
116+
117+
#if TEST_STD_VER >= 14
118+
template <typename Test<char>::Sub TestSub>
119+
constexpr void testConstexprDetail() {
120+
constexpr std::string_view sv{"ABCDE", 5};
121+
{
122+
constexpr std::string_view sv2 = (sv.*TestSub)(0, 3);
123+
124+
static_assert(sv2.size() == 3, "");
125+
static_assert(sv2[0] == 'A', "");
126+
static_assert(sv2[1] == 'B', "");
127+
static_assert(sv2[2] == 'C', "");
128+
}
129+
130+
{
131+
constexpr std::string_view sv2 = (sv.*TestSub)(3, 0);
132+
static_assert(sv2.size() == 0, "");
133+
}
134+
135+
{
136+
constexpr std::string_view sv2 = (sv.*TestSub)(3, 3);
137+
static_assert(sv2.size() == 2, "");
138+
static_assert(sv2[0] == 'D', "");
139+
static_assert(sv2[1] == 'E', "");
140+
}
141+
}
142+
143+
void test_constexpr() {
144+
testConstexprDetail<&std::string_view::substr>();
145+
# if TEST_STD_VER >= 26
146+
testConstexprDetail<&std::string_view::subview>();
147+
# endif
148+
}
149+
#endif
150+
151+
int main(int, char**) {
152+
test();
153+
#if TEST_STD_VER >= 14
154+
test_constexpr();
155+
#endif
156+
157+
return 0;
158+
}

0 commit comments

Comments
 (0)