diff --git a/libcxx/include/string b/libcxx/include/string index 363f27a51648c..5f1662b87f1bc 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1311,6 +1311,8 @@ public: # if _LIBCPP_STD_VER >= 23 template _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { + using __result_type = decltype(std::move(__op)(data(), auto(__n))); + static_assert(__integer_like<__result_type>, "Operation return type must be integer-like"); size_type __sz = size(); size_type __cap = capacity(); if (__n > __cap) diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp index abd284852a189..1b2c134cf4527 100644 --- a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// REQUIRES: std-at-least-c++23 // @@ -21,6 +21,7 @@ #include "make_string.h" #include "test_macros.h" #include "asan_testing.h" +#include "type_algorithms.h" template constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) { @@ -77,17 +78,30 @@ constexpr bool test() { return true; } -void test_value_categories() { +constexpr bool test_value_categories() { std::string s; s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; }); LIBCPP_ASSERT(is_string_asan_correct(s)); s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; }); LIBCPP_ASSERT(is_string_asan_correct(s)); struct RefQualified { - int operator()(char*, std::size_t) && { return 0; } + constexpr int operator()(char*, std::size_t) && { return 0; } }; s.resize_and_overwrite(10, RefQualified{}); LIBCPP_ASSERT(is_string_asan_correct(s)); + return true; +} + +constexpr bool test_integer_like_return_types() { + types::for_each(types::integer_types(), [] { + std::string s; + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> IntegerType { + std::fill(p, p + n, 'f'); + return n; + }); + assert(s.size() == 10); + }); + return true; } int main(int, char**) { @@ -105,5 +119,12 @@ int main(int, char**) { test, std::allocator>>(); static_assert(test, std::allocator>>()); #endif + + test_value_categories(); + test_integer_like_return_types(); + + static_assert(test_value_categories()); + static_assert(test_integer_like_return_types()); + return 0; } diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp new file mode 100644 index 0000000000000..323f49b72c2c8 --- /dev/null +++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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++23 + +// + +// template +// void resize_and_overwrite(size_type n, Operation op) + +// Verify that the operation's return type must be integer-like + +#include + +void test_bool_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char*, std::size_t) { + return true; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + }); +} + +void test_pointer_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char* p, std::size_t) { + return p; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + // expected-error@*:* {{cannot initialize}} + }); +} + +void test_float_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char*, std::size_t) { + return 5.0f; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + }); +}