Namespaces
Variants

std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite

From cppreference.net
std::basic_string
template < class Operation >
constexpr void resize_and_overwrite ( size_type count, Operation op ) ;
(desde C++23)

Cambia el tamaño de la cadena para contener como máximo count caracteres, utilizando la operación proporcionada por el usuario op para modificar los contenidos posiblemente indeterminados y establecer la longitud. Esto evita el costo de inicializar un std::string de tamaño adecuado cuando se pretende usarlo como un arreglo de caracteres para ser poblado por, por ejemplo, una llamada a API de C.

Esta función realiza los siguientes pasos:

  1. Obtiene almacenamiento contiguo que contiene count + 1 caracteres, y hace que sus primeros k caracteres sean iguales a los primeros k caracteres de * this , donde k es el menor entre count y el resultado de size ( ) antes de la llamada a resize_and_overwrite . Sea p el puntero al primer carácter en el almacenamiento.
    • La igualdad se determina como si se verificara this - > compare ( 0 , k, p, k ) == 0 .
    • Los caracteres en [ p + k , p + count ] pueden tener valores indeterminados.
  2. Evalúa std :: move ( op ) ( p, count ) , sea r el valor de retorno.
  3. Reemplaza el contenido de * this con [ p , p + r ) (lo que establece la longitud de * this a r ). Invalida todos los punteros y referencias al rango [ p , p + count ] .

Si r no es de un tipo similar a entero , el programa está mal formado.

Si se satisface cualquiera de las siguientes condiciones, el comportamiento es indefinido:

  • std :: move ( op ) ( p, count ) lanza una excepción.
  • std :: move ( op ) ( p, count ) modifica p o count .
  • r no está en el rango [ 0 , count ] .
  • Cualquier carácter en el rango [ p , p + r ) tiene un valor indeterminado.

Se recomienda que las implementaciones eviten copias y asignaciones innecesarias haciendo, por ejemplo, que p sea igual al puntero al inicio del almacenamiento de caracteres asignado para * this después de la llamada, que puede ser idéntico al almacenamiento existente de * this si count es menor o igual que capacity ( ) .

Contenidos

Parámetros

count - el tamaño máximo posible nuevo de la cadena
op - el objeto función utilizado para establecer los nuevos contenidos de la cadena

Excepciones

std::length_error si count > max_size ( ) . Cualquier excepción lanzada por el correspondiente Allocator .

Si se lanza una excepción desde std :: move ( op ) ( p, count ) , el comportamiento es indefinido. De lo contrario, si se lanza una excepción, esta función no tiene efecto.

Notas

resize_and_overwrite invalida todos los iteradores, punteros y referencias a * this , independientemente de si ocurre realocación. Las implementaciones pueden asumir que el contenido del string no está aliado después de la llamada a resize_and_overwrite .

Macro de prueba de características Valor Std Característica
__cpp_lib_string_resize_and_overwrite 202110L (C++23) std::basic_string::resize_and_overwrite

Ejemplo

Enlace para probar el ejemplo: 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[]{"manzana", "banana", "coco", "fecha", "elderberry"};
int main()
{
    // Un caso simple, añadir solo fruits[0]. El tamaño de la cadena se incrementará.
    std::string s{"Alimentos: "};
    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';
    // El caso de reducción de tamaño. Nótese que la lambda del usuario siempre se invoca.
    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. Copiar datos hasta que el buffer esté lleno. Imprimir datos y tamaños.\n";
    std::string food{"Comida:"};
    const auto resize_to{27};
    std::cout << "Inicialmente, food.size: " << food.size()
              << ", food.capacity: " << food.capacity()
              << ", resize_to: " << resize_to
              << ", comida: " << 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] es el rango asignable
            // p[0]..p[min(n, food_size) - 1] es el rango legible
            // (contenido inicialmente igual a la cadena original)
            // Impresión de depuración:
            std::cout << "En Operación(); n: " << n << '\n';
            // Copiar frutas al búfer p mientras haya suficiente espacio.
            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)};
            // Impresión de depuración:
            std::cout << "In Operation(); final_size: " << final_size << '\n';
            assert(final_size <= n);
            return final_size; // El valor de retorno es la longitud real nueva
                               // de la cadena, debe estar en el rango 0..n
        }
    );
    std::cout << "Finalmente, food.size: " << food.size()
              << ", food.capacity: " << food.capacity()
              << ", comida: " << std::quoted(food) << '\n';
}

Salida posible:

1. "Food: apple"
2. "Food"
3. Copiar datos hasta que el búfer esté lleno. Imprimir datos y tamaños.
Inicialmente, food.size: 5, food.capacity: 15, resize_to: 27, food: "Food:"
En Operation(); n: 27
En Operation(); final_size: 26
Finalmente, food.size: 26, food.capacity: 30, food: "Food: apple banana coconut"

Véase también

cambia el número de caracteres almacenados
(función miembro pública)