forked from OSchip/llvm-project
[libc++] Implement P1072R10 (std::basic_string::resize_and_overwrite)
Reviewed By: Quuxplusone, #libc, Mordante Spies: mzeren-vmw, ckennelly, arichardson, ldionne, Mordante, libcxx-commits, Quuxplusone Differential Revision: https://reviews.llvm.org/D113013
This commit is contained in:
parent
7607ddd981
commit
bec50db2ed
|
@ -328,6 +328,8 @@ Status
|
|||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_string_contains`` ``202011L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_string_resize_and_overwrite`` ``202110L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_to_underlying`` ``202102L``
|
||||
================================================= =================
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``any_invocable``","October 2021","",""
|
||||
"`P0798R8 <https://wg21.link/P0798R8>`__","LWG","Monadic operations for ``std::optional``","October 2021","|Complete|","14.0"
|
||||
"`P0849R8 <https://wg21.link/P0849R8>`__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","|Complete|","14.0"
|
||||
"`P1072R10 <https://wg21.link/P1072R10>`__","LWG","``basic_string::resize_and_overwrite``","October 2021","",""
|
||||
"`P1072R10 <https://wg21.link/P1072R10>`__","LWG","``basic_string::resize_and_overwrite``","October 2021","|Complete|","14.0"
|
||||
"`P1147R1 <https://wg21.link/P1147R1>`__","LWG","Printing ``volatile`` Pointers","October 2021","|Complete|","14.0"
|
||||
"`P1272R4 <https://wg21.link/P1272R4>`__","LWG","Byteswapping for fun&&nuf","October 2021","|Complete|","14.0"
|
||||
"`P1675R2 <https://wg21.link/P1675R2>`__","LWG","``rethrow_exception`` must be allowed to copy","October 2021","",""
|
||||
|
|
|
|
@ -158,6 +158,9 @@ public:
|
|||
void resize(size_type n, value_type c);
|
||||
void resize(size_type n);
|
||||
|
||||
template<class Operation>
|
||||
constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23
|
||||
|
||||
void reserve(size_type res_arg);
|
||||
void reserve(); // deprecated in C++20
|
||||
void shrink_to_fit();
|
||||
|
@ -973,6 +976,17 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());}
|
||||
|
||||
void reserve(size_type __requested_capacity);
|
||||
|
||||
#if _LIBCPP_STD_VER > 20
|
||||
template <class _Op>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
void resize_and_overwrite(size_type __n, _Op __op) {
|
||||
__resize_default_init(__n);
|
||||
pointer __data = data();
|
||||
__erase_to_end(_VSTD::move(__op)(__data, __n));
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void __resize_default_init(size_type __n);
|
||||
|
||||
_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY
|
||||
|
|
|
@ -155,6 +155,7 @@ __cpp_lib_stacktrace 202011L <stacktrace>
|
|||
__cpp_lib_starts_ends_with 201711L <string> <string_view>
|
||||
__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_udls 201304L <string>
|
||||
__cpp_lib_string_view 201803L <string> <string_view>
|
||||
201606L // C++17
|
||||
|
@ -375,6 +376,7 @@ __cpp_lib_void_t 201411L <type_traits>
|
|||
// # define __cpp_lib_stacktrace 202011L
|
||||
// # define __cpp_lib_stdatomic_h 202011L
|
||||
# define __cpp_lib_string_contains 202011L
|
||||
# define __cpp_lib_string_resize_and_overwrite 202110L
|
||||
# define __cpp_lib_to_underlying 202102L
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
__cpp_lib_nonmember_container_access 201411L [C++17]
|
||||
__cpp_lib_starts_ends_with 201711L [C++20]
|
||||
__cpp_lib_string_contains 202011L [C++2b]
|
||||
__cpp_lib_string_resize_and_overwrite 202110L [C++2b]
|
||||
__cpp_lib_string_udls 201304L [C++14]
|
||||
__cpp_lib_string_view 201606L [C++17]
|
||||
201803L [C++20]
|
||||
|
@ -61,6 +62,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should not be defined before c++14"
|
||||
# endif
|
||||
|
@ -99,6 +104,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++14"
|
||||
# endif
|
||||
|
@ -146,6 +155,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++17"
|
||||
# endif
|
||||
|
@ -214,6 +227,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++20"
|
||||
# endif
|
||||
|
@ -285,6 +302,13 @@
|
|||
# error "__cpp_lib_string_contains should have the value 202011L in c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_string_resize_and_overwrite != 202110L
|
||||
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++2b"
|
||||
# endif
|
||||
|
|
|
@ -144,6 +144,7 @@
|
|||
__cpp_lib_starts_ends_with 201711L [C++20]
|
||||
__cpp_lib_stdatomic_h 202011L [C++2b]
|
||||
__cpp_lib_string_contains 202011L [C++2b]
|
||||
__cpp_lib_string_resize_and_overwrite 202110L [C++2b]
|
||||
__cpp_lib_string_udls 201304L [C++14]
|
||||
__cpp_lib_string_view 201606L [C++17]
|
||||
201803L [C++20]
|
||||
|
@ -676,6 +677,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should not be defined before c++14"
|
||||
# endif
|
||||
|
@ -1309,6 +1314,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++14"
|
||||
# endif
|
||||
|
@ -2128,6 +2137,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++17"
|
||||
# endif
|
||||
|
@ -3274,6 +3287,10 @@
|
|||
# error "__cpp_lib_string_contains should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++20"
|
||||
# endif
|
||||
|
@ -4564,6 +4581,13 @@
|
|||
# error "__cpp_lib_string_contains should have the value 202011L in c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_resize_and_overwrite
|
||||
# error "__cpp_lib_string_resize_and_overwrite should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_string_resize_and_overwrite != 202110L
|
||||
# error "__cpp_lib_string_resize_and_overwrite should have the value 202110L in c++2b"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_string_udls
|
||||
# error "__cpp_lib_string_udls should be defined in c++2b"
|
||||
# endif
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <string>
|
||||
|
||||
// template<class Operation>
|
||||
// void resize_and_overwrite(size_type n, Operation op)
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "make_string.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class S>
|
||||
constexpr void test_appending(size_t k, size_t N, size_t new_capacity) {
|
||||
assert(N > k);
|
||||
assert(new_capacity >= N);
|
||||
auto s = S(k, 'a');
|
||||
s.resize_and_overwrite(new_capacity, [&](auto* p, auto n) {
|
||||
assert(n == new_capacity);
|
||||
LIBCPP_ASSERT(s.size() == new_capacity);
|
||||
LIBCPP_ASSERT(s.begin().base() == p);
|
||||
assert(std::all_of(p, p + k, [](const auto ch) { return ch == 'a'; }));
|
||||
std::fill(p + k, p + n, 'b');
|
||||
p[n] = 'c'; // will be overwritten
|
||||
return N;
|
||||
});
|
||||
const S expected = S(k, 'a') + S(N - k, 'b');
|
||||
assert(s == expected);
|
||||
assert(s.c_str()[N] == '\0');
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_truncating(size_t o, size_t N) {
|
||||
assert(N < o);
|
||||
auto s = S(o, 'a');
|
||||
s.resize_and_overwrite(N, [&](auto* p, auto n) {
|
||||
assert(n == N);
|
||||
LIBCPP_ASSERT(s.size() == n);
|
||||
LIBCPP_ASSERT(s.begin().base() == p);
|
||||
assert(std::all_of(p, p + n, [](auto ch) { return ch == 'a'; }));
|
||||
p[n - 1] = 'b';
|
||||
p[n] = 'c'; // will be overwritten
|
||||
return n;
|
||||
});
|
||||
const S expected = S(N - 1, 'a') + S(1, 'b');
|
||||
assert(s == expected);
|
||||
assert(s.c_str()[N] == '\0');
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr bool test() {
|
||||
using S = std::basic_string<CharT>;
|
||||
test_appending<S>(10, 15, 15);
|
||||
test_appending<S>(10, 15, 20);
|
||||
test_appending<S>(10, 40, 40);
|
||||
test_appending<S>(10, 40, 50);
|
||||
test_appending<S>(30, 35, 35);
|
||||
test_appending<S>(30, 35, 45);
|
||||
test_appending<S>(10, 15, 30);
|
||||
test_truncating<S>(15, 10);
|
||||
test_truncating<S>(40, 35);
|
||||
test_truncating<S>(40, 10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void test_value_categories() {
|
||||
std::string s;
|
||||
s.resize_and_overwrite(10, [](char*&, size_t&) { return 0; });
|
||||
struct RefQualified {
|
||||
int operator()(char*, size_t) && { return 0; }
|
||||
};
|
||||
s.resize_and_overwrite(10, RefQualified{});
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>();
|
||||
test<char8_t>();
|
||||
test<char16_t>();
|
||||
test<char32_t>();
|
||||
|
||||
#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
|
||||
static_assert(test<char>());
|
||||
static_assert(test<char8_t>());
|
||||
static_assert(test<char16_t>());
|
||||
static_assert(test<char32_t>());
|
||||
#endif
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>();
|
||||
#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
|
||||
static_assert(test<wchar_t>());
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -624,6 +624,10 @@ feature_test_macros = [ add_version_header(x) for x in [
|
|||
"name": "__cpp_lib_string_contains",
|
||||
"values": { "c++2b": 202011 },
|
||||
"headers": ["string", "string_view"],
|
||||
}, {
|
||||
"name": "__cpp_lib_string_resize_and_overwrite",
|
||||
"values": { "c++2b": 202110 },
|
||||
"headers": ["string"],
|
||||
}, {
|
||||
"name": "__cpp_lib_string_udls",
|
||||
"values": { "c++14": 201304 },
|
||||
|
|
Loading…
Reference in New Issue