diff --git a/libcxx/include/string b/libcxx/include/string index dc562e0207630..043533a4b599d 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..7d4a415227fae 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 @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -77,17 +78,65 @@ 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() { + std::string s; + + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> int { + (void)n; + std::fill(p, p + 5, 'a'); + return 5; + }); + assert(s.size() == 5); + + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned int { + (void)n; + std::fill(p, p + 3, 'b'); + return 3u; + }); + assert(s.size() == 3); + + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> long { + (void)n; + std::fill(p, p + 7, 'c'); + return 7l; + }); + assert(s.size() == 7); + + s.resize_and_overwrite(20, [](char* p, std::size_t n) -> unsigned long { + (void)n; + std::fill(p, p + 4, 'd'); + return 4ul; + }); + assert(s.size() == 4); + + s.resize_and_overwrite(15, [](char* p, std::size_t n) -> long long { + (void)n; + std::fill(p, p + 8, 'e'); + return 8ll; + }); + assert(s.size() == 8); + + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned long long { + std::fill(p, p + n, 'f'); + return n; + }); + assert(s.size() == 10); + + return true; } int main(int, char**) { @@ -105,5 +154,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..1345fde296a20 --- /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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// + +// 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}} + }); +}