Spec-Zone.ru › C++

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.

Эта функция выполняет следующие шаги:

  1. Получает непрерывную область памяти, содержащую count + 1 символов, и делает первые k символов этой области равными первым k символам *this, где k — меньшее из count и результата size() перед вызовом resize_and_overwrite. Пусть p обозначает указатель на первый символ в этой области памяти.
    • Равенство определяется так, как если бы проверялось this->compare(0, k, p, k) == 0.
    • Символы в [p + k, p + count] могут иметь неопределённые значения.
  2. Вычисляет std::move(op)(p, count); пусть r — возвращаемое значение.
  3. Заменяет содержимое *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

Пример

Ссылка для проверки примера: обозреватель компиляторов.

#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';
}

Возможный вывод:

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"

См. также

resize
изменяет количество хранимых символов
(открытая функция-член)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/string/basic_string/resize_and_overwrite

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API