Skip to content

[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
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_string_resize_and_overwrite`` ``202110L``
---------------------------------------------------------- -----------------
``__cpp_lib_string_subview`` ``202506L``
---------------------------------------------------------- -----------------
``__cpp_lib_to_underlying`` ``202102L``
---------------------------------------------------------- -----------------
``__cpp_lib_tuple_like`` *unimplemented*
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/22.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Implemented Papers
------------------

- P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release)
- P3044R2: sub-``string_view`` from ``string`` (`Github <https://github.com/llvm/llvm-project/issues/148140>`__)

Improvements and New Features
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
"`P3179R9 <https://wg21.link/P3179R9>`__","Parallel Range Algorithms","2025-06 (Sofia)","","",""
"`P3709R2 <https://wg21.link/P3709R2>`__","Reconsider parallel ``ranges::rotate_copy`` and ``ranges::reverse_copy``","2025-06 (Sofia)","","",""
"`P3641R0 <https://wg21.link/P3641R0>`__","Rename ``std::observable`` to ``std::observable_checkpoint``, and add a feature-test macro","2025-06 (Sofia)","","",""
"`P3044R2 <https://wg21.link/P3044R2>`__","sub-``string_view`` from ``string``","2025-06 (Sofia)","","",""
"`P3044R2 <https://wg21.link/P3044R2>`__","sub-``string_view`` from ``string``","2025-06 (Sofia)","|Complete|","22",""
"`P2876R3 <https://wg21.link/P2876R3>`__","Proposal to extend ``std::simd`` with more constructors and accessors","2025-06 (Sofia)","","",""
"`P3480R6 <https://wg21.link/P3480R6>`__","``std::simd`` is a range","2025-06 (Sofia)","","",""
"`P2664R11 <https://wg21.link/P2664R11>`__","Extend ``std::simd`` with permutation API","2025-06 (Sofia)","","",""
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1752,6 +1754,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;
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/string_view
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ __cpp_lib_starts_ends_with 201711L <string> <string
__cpp_lib_stdatomic_h 202011L <stdatomic.h>
__cpp_lib_string_contains 202011L <string> <string_view>
__cpp_lib_string_resize_and_overwrite 202110L <string>
__cpp_lib_string_subview 202506L <string> <string_view>
__cpp_lib_string_udls 201304L <string>
__cpp_lib_string_view 202403L <string> <string_view>
201803L // C++20
Expand Down Expand Up @@ -535,6 +536,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_stdatomic_h 202011L
# define __cpp_lib_string_contains 202011L
# define __cpp_lib_string_resize_and_overwrite 202110L
# define __cpp_lib_string_subview 202506L
# define __cpp_lib_to_underlying 202102L
// # define __cpp_lib_tuple_like 202207L
# define __cpp_lib_unreachable 202202L
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should not be defined before c++14"
# endif
Expand Down Expand Up @@ -114,6 +118,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++14"
# endif
Expand Down Expand Up @@ -177,6 +185,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++17"
# endif
Expand Down Expand Up @@ -261,6 +273,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++20"
# endif
Expand Down Expand Up @@ -354,6 +370,13 @@
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++23"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++23"
# endif
Expand Down Expand Up @@ -456,6 +479,13 @@
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++26"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++26"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++26"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++26"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
# error "__cpp_lib_string_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_view
# error "__cpp_lib_string_view should not be defined before c++17"
# endif
Expand All @@ -66,6 +70,10 @@
# error "__cpp_lib_string_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_view
# error "__cpp_lib_string_view should not be defined before c++17"
# endif
Expand All @@ -92,6 +100,10 @@
# error "__cpp_lib_string_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++17"
# endif
Expand Down Expand Up @@ -136,6 +148,10 @@
# error "__cpp_lib_string_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++20"
# endif
Expand Down Expand Up @@ -183,6 +199,13 @@
# error "__cpp_lib_string_contains should have the value 202011L in c++23"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++23"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++23"
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++23"
# endif
Expand Down Expand Up @@ -239,6 +262,13 @@
# error "__cpp_lib_string_contains should have the value 202011L in c++26"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++26"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++26"
# endif

# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++26"
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should not be defined before c++14"
# endif
Expand Down Expand Up @@ -1775,6 +1779,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++14"
# endif
Expand Down Expand Up @@ -2916,6 +2924,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++17"
# endif
Expand Down Expand Up @@ -4330,6 +4342,10 @@
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++23"
# endif

# ifdef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should not be defined before c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++20"
# endif
Expand Down Expand Up @@ -5978,6 +5994,13 @@
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++23"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++23"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++23"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++23"
# endif
Expand Down Expand Up @@ -7947,6 +7970,13 @@
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++26"
# endif

# ifndef __cpp_lib_string_subview
# error "__cpp_lib_string_subview should be defined in c++26"
# endif
# if __cpp_lib_string_subview != 202506L
# error "__cpp_lib_string_subview should have the value 202506L in c++26"
# endif

# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++26"
# endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//===----------------------------------------------------------------------===//
//
// 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>

#include "constexpr_char_traits.h"
#include "make_string.h"
#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"

#define CS(S) MAKE_CSTRING(CharT, S)

template <typename CharT, typename TraitsT, typename AllocT>
constexpr void test() {
std::basic_string<CharT, TraitsT, AllocT> s{CS("Hello cruel world!"), AllocT{}};

{ // With a default position and a character length.
std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview();
assert(sv == CS("Hello cruel world!"));
}

{ // With a explict position and a character length.
std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(6, 5);
assert(sv == CS("cruel"));
}

{ // From the beginning of the string with a explicit character length.
std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, 5);
assert(sv == CS("Hello"));
}

{ // To the end of string with the default character length.
std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(12);
assert(sv == CS("world!"));
}

{ // From the beginning to the end of the string with explicit values.
std::same_as<std::basic_string_view<CharT, TraitsT>> decltype(auto) sv = s.subview(0, s.size());
assert(sv == CS("Hello cruel world!"));
}
}

template <typename CharT>
constexpr void test() {
test<CharT, std::char_traits<CharT>, std::allocator<CharT>>();
test<CharT, std::char_traits<CharT>, min_allocator<CharT>>();
test<CharT, std::char_traits<CharT>, safe_allocator<CharT>>();
test<CharT, std::char_traits<CharT>, test_allocator<CharT>>();

test<CharT, constexpr_char_traits<CharT>, std::allocator<CharT>>();
test<CharT, constexpr_char_traits<CharT>, min_allocator<CharT>>();
test<CharT, constexpr_char_traits<CharT>, safe_allocator<CharT>>();
test<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>();
}

constexpr bool test() {
test<char>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
#endif
#ifndef TEST_HAS_NO_CHAR8_T
test<char8_t>();
#endif
test<char16_t>();
test<char32_t>();

return true;
}

int main(int, char**) {
test();
static_assert(test());

return 0;
}
Loading
Loading