std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite
template
<
class
Operation
>
constexpr void resize_and_overwrite ( size_type count, Operation op ) ; |
(since C++23) | |
Resizes the string to contain at most count characters, using the user-provided operation op to modify the possibly indeterminate contents and set the length. This avoids the cost of initializing a suitably-sized std::string when it is intended to be used as a char array to be populated by, e.g., a C API call.
This function performs following steps:
-
Obtains contiguous storage that contains
count
+
1
characters, and makes its first
k
characters equal to the first
k
characters of
*
this
, where
k
is the smaller of
count
and the result of
size
(
)
before the call to
resize_and_overwrite
. Let p denote the pointer to the first character in the storage.- The equality is determined as if by checking this - > compare ( 0 , k, p, k ) == 0 .
-
The characters in
[
p + k,
p + count]
may have indeterminate values.
- Evaluates std :: move ( op ) ( p, count ) , let r be the return value.
-
Replaces the contents of
*
this
with
[
p,
p + r)
(which sets the length of * this to r ). Invalidates all pointers and references to the range[
p,
p + count]
.
If r is not of an integer-like type , the program is ill-formed.
If any of the following conditions is satisfied, the behavior is undefined:
- std :: move ( op ) ( p, count ) throws an exception.
- std :: move ( op ) ( p, count ) modifies p or count .
-
r
is not in the range
[
0 ,
count]
. -
Any character in range
[
p,
p + r)
has an indeterminate value.
Implementations are recommended to avoid unnecessary copies and allocations by, e.g., making
p
equal to the pointer to beginning of storage of characters allocated for
*
this
after the call, which can be identical to the existing storage of
*
this
if
count
is less than or equal to
capacity
(
)
.
Parameters
count | - | the maximal possible new size of the string |
op | - | the function object used for setting the new contents of the string |
Exceptions
std::length_error
if
count
>
max_size
(
)
.
Any exceptions thrown by corresponding
Allocator
.
If an exception is thrown from std :: move ( op ) ( p, count ) , the behavior is undefined. Otherwise, if an exception is thrown, this function has no effect.
Notes
resize_and_overwrite
invalidates all iterators, pointers, and references into
*
this
, regardless whether reallocation occurs. Implementations may assume that the contents of the string are not aliased after the call to
resize_and_overwrite
.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_string_resize_and_overwrite
|
202110L | (C++23) |
std::basic_string::resize_and_overwrite
|
Example
Link to test the example: compiler explorer .
#include <algorithm> #include <cassert> #include <cstddef> #include <cstring> #include <iomanip> #include <iostream> #include <string> #include <string_view> static_assert(__cpp_lib_string_resize_and_overwrite); constexpr std::string_view fruits[]{"apple", "banana", "coconut", "date", "elderberry"}; int main() { // A simple case, append only fruits[0]. The string size will be increased. std::string s{"Food: "}; s.resize_and_overwrite(16, [sz = s.size()](char* buf, std::size_t buf_size) noexcept { const auto to_copy = std::min(buf_size - sz, fruits[0].size()); std::memcpy(buf + sz, fruits[0].data(), to_copy); return sz + to_copy; }); std::cout << "1. " << std::quoted(s) << '\n'; // The size shrinking case. Note, that the user's lambda is always invoked. s.resize_and_overwrite(10, [](char* buf, int n) noexcept { return std::find(buf, buf + n, ':') - buf; }); std::cout << "2. " << std::quoted(s) << '\n'; std::cout << "3. Copy data until the buffer is full. Print data and sizes.\n"; std::string food{"Food:"}; const auto resize_to{27}; std::cout << "Initially, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", resize_to: " << resize_to << ", food: " << std::quoted(food) << '\n'; food.resize_and_overwrite ( resize_to, [food_size = food.size()](char* p, std::size_t n) noexcept -> std::size_t { // p[0]..p[n] is the assignable range // p[0]..p[min(n, food_size) - 1] is the readable range // (contents initially equal to the original string) // Debug print: std::cout << "In Operation(); n: " << n << '\n'; // Copy fruits to the buffer p while there is enough space. char* first = p + food_size; for (char* const end = p + n; const std::string_view fruit : fruits) { char* last = first + fruit.size() + 1; if (last > end) break; *first++ = ' '; std::ranges::copy(fruit, first); first = last; } const auto final_size{static_cast<std::size_t>(first - p)}; // Debug print: std::cout << "In Operation(); final_size: " << final_size << '\n'; assert(final_size <= n); return final_size; // Return value is the actual new length // of the string, must be in range 0..n } ); std::cout << "Finally, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", food: " << std::quoted(food) << '\n'; }
Possible output:
1. "Food: apple" 2. "Food" 3. Copy data until the buffer is full. Print data and sizes. Initially, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:" In Operation(); n: 27 In Operation(); final_size: 26 Finally, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"
See also
changes the number of characters stored
(public member function) |