forked from OSchip/llvm-project
[libc++] Implement P2438R2 (std::string::substr() &&)
This doesn't affect our ABI because `std::string::substr()` isn't in the dylib and the mangling of `substr() const` and `substr() const&` are different. Reviewed By: ldionne, Mordante, var-const, avogelsgesang, #libc Spies: arphaman, huixie90, libcxx-commits Differential Revision: https://reviews.llvm.org/D131668
This commit is contained in:
parent
001d18664f
commit
29378ab24b
|
@ -46,6 +46,7 @@ Implemented Papers
|
|||
``from_chars`` for Integral Types in ``<charconv>`` Header
|
||||
- P0220R1 - Adopt Library Fundamentals V1 TS Components for C++17
|
||||
- P0482R6 - char8_t: A type for UTF-8 characters and strings
|
||||
- P2438R2 - ``std::string::substr() &&``
|
||||
|
||||
Improvements and New Features
|
||||
-----------------------------
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
"`P2408R5 <https://wg21.link/P2408R5>`__","LWG","Ranges iterators as inputs to non-Ranges algorithms","July 2022","",""
|
||||
"`P2417R2 <https://wg21.link/P2417R2>`__","LWG","A more ``constexpr`` ``bitset``","July 2022","|Complete|","16.0"
|
||||
"`P2419R2 <https://wg21.link/P2419R2>`__","LWG","Clarify handling of encodings in localized formatting of chrono types","July 2022","",""
|
||||
"`P2438R2 <https://wg21.link/P2438R2>`__","LWG","``std::string::substr() &&``","July 2022","",""
|
||||
"`P2438R2 <https://wg21.link/P2438R2>`__","LWG","``std::string::substr() &&``","July 2022","|Complete|","16.0"
|
||||
"`P2445R1 <https://wg21.link/P2445R1>`__","LWG","``forward_like``","July 2022","|Complete|","16.0"
|
||||
"`P2446R2 <https://wg21.link/P2446R2>`__","LWG","``views::as_rvalue``","July 2022","",""
|
||||
"`P2460R2 <https://wg21.link/P2460R2>`__","LWG","Relax requirements on ``wchar_t`` to match existing practices","July 2022","",""
|
||||
|
|
|
|
@ -109,6 +109,10 @@ public:
|
|||
const allocator_type& a = allocator_type()); // constexpr since C++20
|
||||
basic_string(const basic_string& str, size_type pos, size_type n,
|
||||
const Allocator& a = Allocator()); // constexpr since C++20
|
||||
constexpr basic_string(
|
||||
basic_string&& str, size_type pos, const Allocator& a = Allocator()); // since C++23
|
||||
constexpr basic_string(
|
||||
basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); // since C++23
|
||||
template<class T>
|
||||
basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20
|
||||
template <class T>
|
||||
|
@ -261,8 +265,9 @@ public:
|
|||
basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>); // constexpr since C++20
|
||||
|
||||
size_type copy(value_type* s, size_type n, size_type pos = 0) const; // constexpr since C++20
|
||||
basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr since C++20
|
||||
|
||||
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
|
||||
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
|
||||
|
@ -897,6 +902,36 @@ public:
|
|||
std::__debug_db_insert_c(this);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 20
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
basic_string(basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator())
|
||||
: basic_string(std::move(__str), __pos, npos, __alloc) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
basic_string(basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator())
|
||||
: __r_(__default_init_tag(), __alloc) {
|
||||
if (__pos > __str.size())
|
||||
__throw_out_of_range();
|
||||
|
||||
auto __len = std::min<size_type>(__n, __str.size() - __pos);
|
||||
if (__alloc_traits::is_always_equal::value || __alloc == __str.__alloc()) {
|
||||
__r_.first() = __str.__r_.first();
|
||||
__str.__default_init();
|
||||
|
||||
_Traits::move(data(), data() + __pos, __len);
|
||||
__set_size(__len);
|
||||
_Traits::assign(data()[__len], value_type());
|
||||
} else {
|
||||
// Perform a copy because the allocators are not compatible.
|
||||
__init(__str.data() + __pos, __len);
|
||||
}
|
||||
|
||||
std::__debug_db_insert_c(this);
|
||||
if (__is_long())
|
||||
std::__debug_db_swap(this, &__str);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a);
|
||||
|
||||
|
@ -1324,8 +1359,24 @@ public:
|
|||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
|
||||
|
||||
// TODO: Maybe don't pass in the allocator. See https://llvm.org/PR57190
|
||||
#if _LIBCPP_STD_VER <= 20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string substr(size_type __pos = 0, size_type __n = npos) const;
|
||||
basic_string substr(size_type __pos = 0, size_type __n = npos) const {
|
||||
return basic_string(*this, __pos, __n, __alloc());
|
||||
}
|
||||
#else
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
basic_string substr(size_type __pos = 0, size_type __n = npos) const& {
|
||||
return basic_string(*this, __pos, __n, __alloc());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
basic_string substr(size_type __pos = 0, size_type __n = npos) && {
|
||||
return basic_string(std::move(*this), __pos, __n, __alloc());
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void swap(basic_string& __str)
|
||||
|
@ -3472,14 +3523,6 @@ basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n,
|
|||
return __rlen;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string<_CharT, _Traits, _Allocator>
|
||||
basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n) const
|
||||
{
|
||||
return basic_string(*this, __pos, __n, __alloc());
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <string>
|
||||
|
||||
// Check that basic_string(basic_string&&, size_type, Allocator) and
|
||||
// basic_string(basic_string&&, size_type, size_type, Allocator) inserts the container into the debug database
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: !libcpp-has-debug-mode, c++03
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace std::string_literals;
|
||||
|
||||
{
|
||||
std::string s = {"Banane"s, 1};
|
||||
auto i = s.begin();
|
||||
assert(i[0] == 'a');
|
||||
TEST_LIBCPP_ASSERT_FAILURE(i[5], "Attempted to subscript an iterator outside its valid range");
|
||||
}
|
||||
{
|
||||
std::string s = {"Banane"s, 0, 5};
|
||||
auto i = s.begin();
|
||||
assert(i[0] == 'B');
|
||||
TEST_LIBCPP_ASSERT_FAILURE(i[5], "Attempted to subscript an iterator outside its valid range");
|
||||
}
|
||||
{
|
||||
std::string s = {"long long string so no SSO"s, 21};
|
||||
auto i = s.begin();
|
||||
assert(i[0] == 'o');
|
||||
TEST_LIBCPP_ASSERT_FAILURE(i[5], "Attempted to subscript an iterator outside its valid range");
|
||||
}
|
||||
{
|
||||
std::string s = {"long long string so no SSO"s, 0, 5};
|
||||
auto i = s.begin();
|
||||
assert(i[0] == 'l');
|
||||
TEST_LIBCPP_ASSERT_FAILURE(i[5], "Attempted to subscript an iterator outside its valid range");
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
#include "min_allocator.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using T = decltype(uint8_t() - uint8_t());
|
||||
{
|
||||
typedef std::string C;
|
||||
C c(1, '\0');
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
// constexpr basic_string(basic_string&& str, size_type pos, const Allocator& a = Allocator());
|
||||
// constexpr basic_string(basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator());
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "constexpr_char_traits.h"
|
||||
#include "count_new.h"
|
||||
#include "make_string.h"
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
#define STR(string) MAKE_CSTRING(typename S::value_type, string)
|
||||
|
||||
constexpr struct should_throw_exception_t {
|
||||
} should_throw_exception;
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos(S orig, typename S::size_type pos, S expected) {
|
||||
#ifdef _LIBCPP_VERSION
|
||||
ConstexprDisableAllocationGuard g;
|
||||
#endif
|
||||
S substr(std::move(orig), pos);
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(orig.empty());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos(S orig, typename S::size_type pos, should_throw_exception_t) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if (!std::is_constant_evaluated()) {
|
||||
try {
|
||||
[[maybe_unused]] S substr = S(std::move(orig), pos);
|
||||
assert(false);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)orig;
|
||||
(void)pos;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void
|
||||
test_string_pos_alloc(S orig, typename S::size_type pos, const typename S::allocator_type& alloc, S expected) {
|
||||
S substr(std::move(orig), pos, alloc);
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
assert(substr.get_allocator() == alloc);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos_alloc(
|
||||
S orig, typename S::size_type pos, const typename S::allocator_type& alloc, should_throw_exception_t) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if (!std::is_constant_evaluated()) {
|
||||
try {
|
||||
[[maybe_unused]] S substr = S(std::move(orig), pos, alloc);
|
||||
assert(false);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)orig;
|
||||
(void)pos;
|
||||
(void)alloc;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos_n(S orig, typename S::size_type pos, typename S::size_type n, S expected) {
|
||||
#ifdef _LIBCPP_VERSION
|
||||
ConstexprDisableAllocationGuard g;
|
||||
#endif
|
||||
S substr(std::move(orig), pos, n);
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(orig.empty());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos_n(S orig, typename S::size_type pos, typename S::size_type n, should_throw_exception_t) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if (!std::is_constant_evaluated()) {
|
||||
try {
|
||||
[[maybe_unused]] S substr = S(std::move(orig), pos, n);
|
||||
assert(false);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)orig;
|
||||
(void)pos;
|
||||
(void)n;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos_n_alloc(
|
||||
S orig, typename S::size_type pos, typename S::size_type n, const typename S::allocator_type& alloc, S expected) {
|
||||
S substr(std::move(orig), pos, n, alloc);
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
assert(substr.get_allocator() == alloc);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string_pos_n_alloc(
|
||||
S orig,
|
||||
typename S::size_type pos,
|
||||
typename S::size_type n,
|
||||
const typename S::allocator_type& alloc,
|
||||
should_throw_exception_t) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if (!std::is_constant_evaluated()) {
|
||||
try {
|
||||
[[maybe_unused]] S substr = S(std::move(orig), pos, n, alloc);
|
||||
assert(false);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)orig;
|
||||
(void)pos;
|
||||
(void)n;
|
||||
(void)alloc;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string(const typename S::allocator_type& alloc) {
|
||||
test_string_pos<S>(STR(""), 0, STR(""));
|
||||
test_string_pos<S>(STR(""), 1, should_throw_exception);
|
||||
test_string_pos<S>(STR("Banane"), 1, STR("anane"));
|
||||
test_string_pos<S>(STR("Banane"), 6, STR(""));
|
||||
test_string_pos<S>(STR("Banane"), 7, should_throw_exception);
|
||||
test_string_pos<S>(STR("long long string so no SSO"), 0, STR("long long string so no SSO"));
|
||||
test_string_pos<S>(STR("long long string so no SSO"), 10, STR("string so no SSO"));
|
||||
test_string_pos<S>(STR("long long string so no SSO"), 26, STR(""));
|
||||
test_string_pos<S>(STR("long long string so no SSO"), 27, should_throw_exception);
|
||||
|
||||
test_string_pos_alloc<S>(STR(""), 0, alloc, STR(""));
|
||||
test_string_pos_alloc<S>(STR(""), 1, alloc, should_throw_exception);
|
||||
test_string_pos_alloc<S>(STR("Banane"), 1, alloc, STR("anane"));
|
||||
test_string_pos_alloc<S>(STR("Banane"), 6, alloc, STR(""));
|
||||
test_string_pos_alloc<S>(STR("Banane"), 7, alloc, should_throw_exception);
|
||||
test_string_pos_alloc<S>(STR("long long string so no SSO"), 0, alloc, STR("long long string so no SSO"));
|
||||
test_string_pos_alloc<S>(STR("long long string so no SSO"), 10, alloc, STR("string so no SSO"));
|
||||
test_string_pos_alloc<S>(STR("long long string so no SSO"), 26, alloc, STR(""));
|
||||
test_string_pos_alloc<S>(STR("long long string so no SSO"), 27, alloc, should_throw_exception);
|
||||
|
||||
test_string_pos_n<S>(STR(""), 0, 0, STR(""));
|
||||
test_string_pos_n<S>(STR(""), 0, 1, STR(""));
|
||||
test_string_pos_n<S>(STR(""), 1, 0, should_throw_exception);
|
||||
test_string_pos_n<S>(STR(""), 1, 1, should_throw_exception);
|
||||
test_string_pos_n<S>(STR("Banane"), 1, 10, STR("anane"));
|
||||
test_string_pos_n<S>(STR("Banane"), 6, 0, STR(""));
|
||||
test_string_pos_n<S>(STR("Banane"), 6, 5, STR(""));
|
||||
test_string_pos_n<S>(STR("Banane"), 7, 10, should_throw_exception);
|
||||
test_string_pos_n<S>(STR("long long string so no SSO"), 0, 10, STR("long long "));
|
||||
test_string_pos_n<S>(STR("long long string so no SSO"), 10, 8, STR("string s"));
|
||||
test_string_pos_n<S>(STR("long long string so no SSO"), 20, 10, STR("no SSO"));
|
||||
test_string_pos_n<S>(STR("long long string so no SSO"), 26, 10, STR(""));
|
||||
test_string_pos_n<S>(STR("long long string so no SSO"), 27, 10, should_throw_exception);
|
||||
|
||||
test_string_pos_n_alloc<S>(STR(""), 0, 0, alloc, STR(""));
|
||||
test_string_pos_n_alloc<S>(STR(""), 0, 1, alloc, STR(""));
|
||||
test_string_pos_n_alloc<S>(STR(""), 1, 0, alloc, should_throw_exception);
|
||||
test_string_pos_n_alloc<S>(STR(""), 1, 1, alloc, should_throw_exception);
|
||||
test_string_pos_n_alloc<S>(STR("Banane"), 1, 10, alloc, STR("anane"));
|
||||
test_string_pos_n_alloc<S>(STR("Banane"), 6, 0, alloc, STR(""));
|
||||
test_string_pos_n_alloc<S>(STR("Banane"), 6, 5, alloc, STR(""));
|
||||
test_string_pos_n_alloc<S>(STR("Banane"), 7, 10, alloc, should_throw_exception);
|
||||
test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 0, 10, alloc, STR("long long "));
|
||||
test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 10, 8, alloc, STR("string s"));
|
||||
test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 20, 10, alloc, STR("no SSO"));
|
||||
test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 26, 10, alloc, STR(""));
|
||||
test_string_pos_n_alloc<S>(STR("long long string so no SSO"), 27, 10, alloc, should_throw_exception);
|
||||
}
|
||||
|
||||
template <class CharT, class CharTraits>
|
||||
constexpr void test_allocators() {
|
||||
test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>(std::allocator<CharT>{});
|
||||
test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>(min_allocator<CharT>{});
|
||||
test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>(test_allocator<CharT>{42});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr bool test_char_traits() {
|
||||
test_allocators<CharT, std::char_traits<CharT>>();
|
||||
test_allocators<CharT, constexpr_char_traits<CharT>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
// TODO: put these into a single function when we increase the constexpr step limit
|
||||
test_char_traits<char>();
|
||||
static_assert(test_char_traits<char>());
|
||||
test_char_traits<char16_t>();
|
||||
static_assert(test_char_traits<char16_t>());
|
||||
test_char_traits<char32_t>();
|
||||
static_assert(test_char_traits<char32_t>());
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test_char_traits<wchar_t>();
|
||||
static_assert(test_char_traits<wchar_t>());
|
||||
#endif
|
||||
#ifndef TEST_HAS_NO_CHAR8_T
|
||||
test_char_traits<char8_t>();
|
||||
static_assert(test_char_traits<char8_t>());
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
// <string>
|
||||
|
||||
// basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr since C++20
|
||||
// basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr since C++20, removed in C++23
|
||||
// basic_string substr(size_type pos = 0, size_type n = npos) const&; // since in C++23
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
@ -47,130 +48,72 @@ test(const S& s, typename S::size_type pos, typename S::size_type n)
|
|||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
test(S(""), 0, 0);
|
||||
test(S(""), 1, 0);
|
||||
test(S("pniot"), 0, 0);
|
||||
test(S("htaob"), 0, 1);
|
||||
test(S("fodgq"), 0, 2);
|
||||
test(S("hpqia"), 0, 4);
|
||||
test(S("qanej"), 0, 5);
|
||||
test(S("dfkap"), 1, 0);
|
||||
test(S("clbao"), 1, 1);
|
||||
test(S("ihqrf"), 1, 2);
|
||||
test(S("mekdn"), 1, 3);
|
||||
test(S("ngtjf"), 1, 4);
|
||||
test(S("srdfq"), 2, 0);
|
||||
test(S("qkdrs"), 2, 1);
|
||||
test(S("ikcrq"), 2, 2);
|
||||
test(S("cdaih"), 2, 3);
|
||||
test(S("dmajb"), 4, 0);
|
||||
test(S("karth"), 4, 1);
|
||||
test(S("lhcdo"), 5, 0);
|
||||
test(S("acbsj"), 6, 0);
|
||||
test(S("pbsjikaole"), 0, 0);
|
||||
test(S("pcbahntsje"), 0, 1);
|
||||
test(S("mprdjbeiak"), 0, 5);
|
||||
test(S("fhepcrntko"), 0, 9);
|
||||
test(S("eqmpaidtls"), 0, 10);
|
||||
test(S("joidhalcmq"), 1, 0);
|
||||
test(S("omigsphflj"), 1, 1);
|
||||
test(S("kocgbphfji"), 1, 4);
|
||||
test(S("onmjekafbi"), 1, 8);
|
||||
test(S("fbslrjiqkm"), 1, 9);
|
||||
test(S("oqmrjahnkg"), 5, 0);
|
||||
test(S("jeidpcmalh"), 5, 1);
|
||||
test(S("schfalibje"), 5, 2);
|
||||
test(S("crliponbqe"), 5, 4);
|
||||
test(S("igdscopqtm"), 5, 5);
|
||||
test(S("qngpdkimlc"), 9, 0);
|
||||
test(S("thdjgafrlb"), 9, 1);
|
||||
test(S("hcjitbfapl"), 10, 0);
|
||||
test(S("mgojkldsqh"), 11, 0);
|
||||
test(S("gfshlcmdjreqipbontak"), 0, 0);
|
||||
test(S("nadkhpfemgclosibtjrq"), 0, 1);
|
||||
test(S("nkodajteqplrbifhmcgs"), 0, 10);
|
||||
test(S("ofdrqmkeblthacpgijsn"), 0, 19);
|
||||
test(S("gbmetiprqdoasckjfhln"), 0, 20);
|
||||
test(S("bdfjqgatlksriohemnpc"), 1, 0);
|
||||
test(S("crnklpmegdqfiashtojb"), 1, 1);
|
||||
test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
|
||||
test(S("jsbtafedocnirgpmkhql"), 1, 18);
|
||||
test(S("prqgnlbaejsmkhdctoif"), 1, 19);
|
||||
test(S("qnmodrtkebhpasifgcjl"), 10, 0);
|
||||
test(S("pejafmnokrqhtisbcdgl"), 10, 1);
|
||||
test(S("cpebqsfmnjdolhkratgi"), 10, 5);
|
||||
test(S("odnqkgijrhabfmcestlp"), 10, 9);
|
||||
test(S("lmofqdhpkibagnrcjste"), 10, 10);
|
||||
test(S("lgjqketopbfahrmnsicd"), 19, 0);
|
||||
test(S("ktsrmnqagdecfhijpobl"), 19, 1);
|
||||
test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
|
||||
test(S("dplqartnfgejichmoskb"), 21, 0);
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
{
|
||||
typedef std::string S;
|
||||
test(S(""), 0, 0);
|
||||
test(S(""), 1, 0);
|
||||
test(S("pniot"), 0, 0);
|
||||
test(S("htaob"), 0, 1);
|
||||
test(S("fodgq"), 0, 2);
|
||||
test(S("hpqia"), 0, 4);
|
||||
test(S("qanej"), 0, 5);
|
||||
test(S("dfkap"), 1, 0);
|
||||
test(S("clbao"), 1, 1);
|
||||
test(S("ihqrf"), 1, 2);
|
||||
test(S("mekdn"), 1, 3);
|
||||
test(S("ngtjf"), 1, 4);
|
||||
test(S("srdfq"), 2, 0);
|
||||
test(S("qkdrs"), 2, 1);
|
||||
test(S("ikcrq"), 2, 2);
|
||||
test(S("cdaih"), 2, 3);
|
||||
test(S("dmajb"), 4, 0);
|
||||
test(S("karth"), 4, 1);
|
||||
test(S("lhcdo"), 5, 0);
|
||||
test(S("acbsj"), 6, 0);
|
||||
test(S("pbsjikaole"), 0, 0);
|
||||
test(S("pcbahntsje"), 0, 1);
|
||||
test(S("mprdjbeiak"), 0, 5);
|
||||
test(S("fhepcrntko"), 0, 9);
|
||||
test(S("eqmpaidtls"), 0, 10);
|
||||
test(S("joidhalcmq"), 1, 0);
|
||||
test(S("omigsphflj"), 1, 1);
|
||||
test(S("kocgbphfji"), 1, 4);
|
||||
test(S("onmjekafbi"), 1, 8);
|
||||
test(S("fbslrjiqkm"), 1, 9);
|
||||
test(S("oqmrjahnkg"), 5, 0);
|
||||
test(S("jeidpcmalh"), 5, 1);
|
||||
test(S("schfalibje"), 5, 2);
|
||||
test(S("crliponbqe"), 5, 4);
|
||||
test(S("igdscopqtm"), 5, 5);
|
||||
test(S("qngpdkimlc"), 9, 0);
|
||||
test(S("thdjgafrlb"), 9, 1);
|
||||
test(S("hcjitbfapl"), 10, 0);
|
||||
test(S("mgojkldsqh"), 11, 0);
|
||||
test(S("gfshlcmdjreqipbontak"), 0, 0);
|
||||
test(S("nadkhpfemgclosibtjrq"), 0, 1);
|
||||
test(S("nkodajteqplrbifhmcgs"), 0, 10);
|
||||
test(S("ofdrqmkeblthacpgijsn"), 0, 19);
|
||||
test(S("gbmetiprqdoasckjfhln"), 0, 20);
|
||||
test(S("bdfjqgatlksriohemnpc"), 1, 0);
|
||||
test(S("crnklpmegdqfiashtojb"), 1, 1);
|
||||
test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
|
||||
test(S("jsbtafedocnirgpmkhql"), 1, 18);
|
||||
test(S("prqgnlbaejsmkhdctoif"), 1, 19);
|
||||
test(S("qnmodrtkebhpasifgcjl"), 10, 0);
|
||||
test(S("pejafmnokrqhtisbcdgl"), 10, 1);
|
||||
test(S("cpebqsfmnjdolhkratgi"), 10, 5);
|
||||
test(S("odnqkgijrhabfmcestlp"), 10, 9);
|
||||
test(S("lmofqdhpkibagnrcjste"), 10, 10);
|
||||
test(S("lgjqketopbfahrmnsicd"), 19, 0);
|
||||
test(S("ktsrmnqagdecfhijpobl"), 19, 1);
|
||||
test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
|
||||
test(S("dplqartnfgejichmoskb"), 21, 0);
|
||||
}
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, 0);
|
||||
test(S(""), 1, 0);
|
||||
test(S("pniot"), 0, 0);
|
||||
test(S("htaob"), 0, 1);
|
||||
test(S("fodgq"), 0, 2);
|
||||
test(S("hpqia"), 0, 4);
|
||||
test(S("qanej"), 0, 5);
|
||||
test(S("dfkap"), 1, 0);
|
||||
test(S("clbao"), 1, 1);
|
||||
test(S("ihqrf"), 1, 2);
|
||||
test(S("mekdn"), 1, 3);
|
||||
test(S("ngtjf"), 1, 4);
|
||||
test(S("srdfq"), 2, 0);
|
||||
test(S("qkdrs"), 2, 1);
|
||||
test(S("ikcrq"), 2, 2);
|
||||
test(S("cdaih"), 2, 3);
|
||||
test(S("dmajb"), 4, 0);
|
||||
test(S("karth"), 4, 1);
|
||||
test(S("lhcdo"), 5, 0);
|
||||
test(S("acbsj"), 6, 0);
|
||||
test(S("pbsjikaole"), 0, 0);
|
||||
test(S("pcbahntsje"), 0, 1);
|
||||
test(S("mprdjbeiak"), 0, 5);
|
||||
test(S("fhepcrntko"), 0, 9);
|
||||
test(S("eqmpaidtls"), 0, 10);
|
||||
test(S("joidhalcmq"), 1, 0);
|
||||
test(S("omigsphflj"), 1, 1);
|
||||
test(S("kocgbphfji"), 1, 4);
|
||||
test(S("onmjekafbi"), 1, 8);
|
||||
test(S("fbslrjiqkm"), 1, 9);
|
||||
test(S("oqmrjahnkg"), 5, 0);
|
||||
test(S("jeidpcmalh"), 5, 1);
|
||||
test(S("schfalibje"), 5, 2);
|
||||
test(S("crliponbqe"), 5, 4);
|
||||
test(S("igdscopqtm"), 5, 5);
|
||||
test(S("qngpdkimlc"), 9, 0);
|
||||
test(S("thdjgafrlb"), 9, 1);
|
||||
test(S("hcjitbfapl"), 10, 0);
|
||||
test(S("mgojkldsqh"), 11, 0);
|
||||
test(S("gfshlcmdjreqipbontak"), 0, 0);
|
||||
test(S("nadkhpfemgclosibtjrq"), 0, 1);
|
||||
test(S("nkodajteqplrbifhmcgs"), 0, 10);
|
||||
test(S("ofdrqmkeblthacpgijsn"), 0, 19);
|
||||
test(S("gbmetiprqdoasckjfhln"), 0, 20);
|
||||
test(S("bdfjqgatlksriohemnpc"), 1, 0);
|
||||
test(S("crnklpmegdqfiashtojb"), 1, 1);
|
||||
test(S("ejqcnahdrkfsmptilgbo"), 1, 9);
|
||||
test(S("jsbtafedocnirgpmkhql"), 1, 18);
|
||||
test(S("prqgnlbaejsmkhdctoif"), 1, 19);
|
||||
test(S("qnmodrtkebhpasifgcjl"), 10, 0);
|
||||
test(S("pejafmnokrqhtisbcdgl"), 10, 1);
|
||||
test(S("cpebqsfmnjdolhkratgi"), 10, 5);
|
||||
test(S("odnqkgijrhabfmcestlp"), 10, 9);
|
||||
test(S("lmofqdhpkibagnrcjste"), 10, 10);
|
||||
test(S("lgjqketopbfahrmnsicd"), 19, 0);
|
||||
test(S("ktsrmnqagdecfhijpobl"), 19, 1);
|
||||
test(S("lsaijeqhtrbgcdmpfkno"), 20, 0);
|
||||
test(S("dplqartnfgejichmoskb"), 21, 0);
|
||||
}
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
// constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "constexpr_char_traits.h"
|
||||
#include "make_string.h"
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
|
||||
#define STR(string) MAKE_CSTRING(typename S::value_type, string)
|
||||
|
||||
constexpr struct should_throw_exception_t {
|
||||
} should_throw_exception;
|
||||
|
||||
template <class S>
|
||||
constexpr void test(S orig, size_t pos, ptrdiff_t n, S expected) {
|
||||
S str = std::move(orig).substr(pos, n);
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(str.__invariants());
|
||||
assert(str == expected);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test(S orig, size_t pos, ptrdiff_t n, should_throw_exception_t) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if (!std::is_constant_evaluated()) {
|
||||
try {
|
||||
S str = std::move(orig).substr(pos, n);
|
||||
assert(false);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)orig;
|
||||
(void)pos;
|
||||
(void)n;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class S>
|
||||
constexpr void test_string() {
|
||||
test<S>(STR(""), 0, 0, STR(""));
|
||||
test<S>(STR(""), 0, 1, STR(""));
|
||||
test<S>(STR(""), 1, 0, should_throw_exception);
|
||||
test<S>(STR(""), 1, 1, should_throw_exception);
|
||||
test<S>(STR("short string"), 0, 1, STR("s"));
|
||||
test<S>(STR("short string"), 5, 5, STR(" stri"));
|
||||
test<S>(STR("short string"), 12, 5, STR(""));
|
||||
test<S>(STR("short string"), 13, 5, should_throw_exception);
|
||||
test<S>(STR("long long string so no SSO"), 0, 0, STR(""));
|
||||
test<S>(STR("long long string so no SSO"), 0, 10, STR("long long "));
|
||||
test<S>(STR("long long string so no SSO"), 10, 10, STR("string so "));
|
||||
test<S>(STR("long long string so no SSO"), 20, 10, STR("no SSO"));
|
||||
test<S>(STR("long long string so no SSO"), 26, 10, STR(""));
|
||||
test<S>(STR("long long string so no SSO"), 27, 0, should_throw_exception);
|
||||
}
|
||||
|
||||
template <class CharT, class CharTraits>
|
||||
constexpr void test_allocators() {
|
||||
test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>();
|
||||
test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>();
|
||||
test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr void test_char_traits() {
|
||||
test_allocators<CharT, std::char_traits<CharT>>();
|
||||
test_allocators<CharT, constexpr_char_traits<CharT>>();
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_char_traits<char>();
|
||||
test_char_traits<char16_t>();
|
||||
test_char_traits<char32_t>();
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test_char_traits<wchar_t>();
|
||||
#endif
|
||||
#ifndef TEST_HAS_NO_CHAR8_T
|
||||
test_char_traits<char8_t>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -472,6 +472,40 @@ private:
|
|||
DisableAllocationGuard& operator=(DisableAllocationGuard const&);
|
||||
};
|
||||
|
||||
#if TEST_STD_VER >= 20
|
||||
|
||||
struct ConstexprDisableAllocationGuard {
|
||||
TEST_CONSTEXPR_CXX14 explicit ConstexprDisableAllocationGuard(bool disable = true) : m_disabled(disable)
|
||||
{
|
||||
if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
// Don't re-disable if already disabled.
|
||||
if (globalMemCounter.disable_allocations == true) m_disabled = false;
|
||||
if (m_disabled) globalMemCounter.disableAllocations();
|
||||
} else {
|
||||
m_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 void release() {
|
||||
if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
if (m_disabled) globalMemCounter.enableAllocations();
|
||||
m_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 ~ConstexprDisableAllocationGuard() {
|
||||
release();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_disabled;
|
||||
|
||||
ConstexprDisableAllocationGuard(ConstexprDisableAllocationGuard const&);
|
||||
ConstexprDisableAllocationGuard& operator=(ConstexprDisableAllocationGuard const&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct RequireAllocationGuard {
|
||||
explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
|
||||
: m_req_alloc(RequireAtLeast),
|
||||
|
|
|
@ -89,7 +89,7 @@ struct MultiStringType {
|
|||
// This helper is used in unit tests to make them generic. The input should be
|
||||
// valid ASCII which means the input is also valid UTF-8.
|
||||
#define MAKE_CSTRING(CharT, Str) \
|
||||
MKSTR(Str).as_ptr((const CharT*)0)
|
||||
MKSTR(Str).as_ptr(static_cast<const CharT*>(nullptr))
|
||||
|
||||
// Like MAKE_CSTRING but makes a basic_string<CharT>. Embedded nulls are OK.
|
||||
#define MAKE_STRING(CharT, Str) \
|
||||
|
|
Loading…
Reference in New Issue