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 подходящего размера, когда она предназначена для использования в качестве массива символов для заполнения, например, вызовом API языка C.
Эта функция выполняет следующие шаги:
- Получает непрерывное хранилище, содержащее
count + 1символов, и делает первыеkсимволов равными первымkсимволам*this, гдеk— это меньшее изcountи результатаsize()до вызоваresize_and_overwrite. Пустьpобозначает указатель на первый символ в хранилище.- Равенство определяется как при проверке
this->compare(0, k, p, k) == 0. - Символы в
[p + k,p + count]могут иметь неопределённые значения.
- Равенство определяется как при проверке
- Вычисляет
std::move(op)(p, count), пустьrбудет возвращаемым значением. - Заменяет содержимое
*thisна[p,p + r)(что устанавливает длину*thisравнойr). Аннулирует все указатели и ссылки на диапазон[p,p + count].
Если r не является целочисленным типом, программа считается некорректной.
Если выполняется любое из следующих условий, поведение не определено:
std::move(op)(p, count)выбрасывает исключение.std::move(op)(p, count)изменяетpилиcount.rне находится в диапазоне[0,count].- Любой символ в диапазоне
[p,p + r)имеет неопределённое значение.
Реализациям рекомендуется избегать ненужных копирований и выделений памяти, например, делая p равным указателю на начало хранилища символов, выделенного для *this после вызова, который может быть идентичен существующему хранилищу *this, если count меньше или равно capacity().
Параметры
| count | - | максимально возможный новый размер строки |
| op | - | функциональный объект, используемый для установки нового содержимого строки |
Исключения
std::length_error
если
count
>
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[]{"яблоко", "банан", "кокос", "дата", "бузина"}; int main() { // Простой случай, добавление только fruits[0]. Размер строки будет увеличен. std::string s{"Еда: "}; 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 (Примечание: Согласно требованиям, HTML-теги и атрибуты не переведены, термин `std::quoted` как специфический для C++ оставлен без изменения)(s) << '\n'; // Случай уменьшения размера. Обратите внимание, что пользовательская лямбда всегда вызывается. 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. Копировать данные до заполнения буфера. Вывести данные и размеры.\n"; std::string 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 << "In Operation(); n: " << n << '\n'; // Копировать фрукты в буфер 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 << "In 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() << ", еда: " << std::quoted (Примечание: Согласно требованиям, HTML-теги и атрибуты не переведены, термин `std::quoted` как специфический для C++ оставлен без перевода)(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"
Смотрите также
|
изменяет количество хранимых символов
(публичная функция-член) |