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 функция-элемент) |