std::basic_string<CharT,Traits,Allocator>::resize_and_overwrite
template< class Operation > constexpr void resize_and_overwrite( size_type count, Operation op ); |
(начиная с C++23) | |
Изменяет размер строки так, чтобы она содержала не более count символов, используя предоставленную пользователем операцию op для изменения возможно неопределённого содержимого и установки длины. Это позволяет избежать затрат на инициализацию std::string подходящего размера, когда она предназначена для использования в качестве массива символов для заполнения, например, вызовом C API.
Эта функция выполняет следующие шаги:
- Получает непрерывное хранилище, содержащее count + 1 символов, и делает его первые
k
символы равными первымk
символам *this, гдеk
меньшее из count и результат this->size() перед вызовомresize_and_overwrite
. Пустьp
обозначает указатель на первый символ в хранилище.- Равенство определяется как будто проверкой this->compare
(0, k, p, k) == 0
. - Символы в
[
p + k,
p + count]
могут иметь неопределённые значения.
- Равенство определяется как будто проверкой this->compare
- Вычисляет std::move(op)(p, count). Пусть
r
будет возвращаемым значением std::move(op)(p, count). - Заменяет содержимое *this на
[
p,
p + r)
(что устанавливает длину *this вr
). Делает недействительными все указатели и ссылки на диапазон[
p,
p + count]
.
Программа будет неправильной, если r
не имеет целочисленного типа. Поведение не определено, если std::move(op)(p, count) генерирует исключение или изменяет p
или count, r
не находится в диапазоне [
0,
count]
, или любой символ в диапазоне [
p,
p + r)
имеет неопределённое значение.
Реализациям рекомендуется избегать ненужных копирований и выделений, например, делая p
равным указателю на начало области хранения символов, выделенной для *this после вызова, который может быть идентичен существующему хранилищу *this, если count меньше или равно this->capacity().
Содержание |
[править] Параметры
count | — | максимально возможный новый размер строки |
op | — | функциональный объект, используемый для установки нового содержимого строки |
[править] Возвращаемое значение
(нет)
[править] Исключения
std::length_error, если count > this->
max_size().
Любые исключения, сгенерированные соответствующим Allocator
.
Если из std::move(op)(p, count) генерируется исключение, поведение не определено. Иначе, если возникнет исключение, эта функция не будет иметь никакого эффекта.
[править] Примечание
resize_and_overwrite
делает недействительными все итераторы, указатели и ссылки в *this, независимо от того, происходит ли перераспределение. Реализации могут предполагать, что содержимое строки не имеет псевдонимов после вызова resize_and_overwrite
.
Макрос Тестирования функциональности | Значение | Стандарт | Функциональность |
---|---|---|---|
__cpp_lib_string_resize_and_overwrite |
202110L | (C++23) | std::basic_string::resize_and_overwrite
|
[править] Пример
Ссылка для проверки примера: 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() { // Простой случай: добавляем только fruits[0]. Размер строки будет увеличен. std::string s{"Food: "}; s.resize_and_overwrite(16, [sz = s.size()](char* buf, std::size_t buf_size) { 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'; // Случай для уменьшения размера. Обратите внимание, что лямбда-выражение // пользователя вызывается всегда. s.resize_and_overwrite(10, [](char* buf, int n) { return std::find(buf, buf + n, ':') - buf; }); std::cout << "2. " << std::quoted(s) << '\n'; std::cout << "3. Копирует данные до тех пор, пока буфер не заполнится. " "Распечатывает данные и размеры.\n"; std::string food{"Food:"}; const auto resize_to{27}; std::cout << "Изначально, 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] присваиваемый диапазон // p[0]..p[min(n, food_size) - 1] это читаемый диапазон // (содержимое изначально равно исходной строке) // Отладочная печать: std::cout << "В Operation(); n: " << n << '\n'; // Копирует fruits в буфер p, пока достаточно места. 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)}; // Отладочная печать: std::cout << "В Operation(); final_size: " << final_size << '\n'; assert(final_size <= n); return final_size; // Возвращаемое значение это фактическая новая длина // строки. Она должна находиться в диапазоне 0..n. }); std::cout << "Окончательно, food.size: " << food.size() << ", food.capacity: " << food.capacity() << ", food: " << std::quoted(food) << '\n'; }
Возможный вывод:
1. "Food: apple" 2. "Food" 3. Копирует данные до тех пор, пока буфер не заполнится. Распечатывает данные и размеры. Изначально, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:" В Operation(); n: 27 В Operation(); final_size: 26 Окончательно, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"
[править] Смотрите также
изменяет количество сохранённых символов (public функция-элемент) |