std::basic_string<CharT,Traits,Allocator>:: resize_and_overwrite
|
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:
-
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.
- Evalúa std :: move ( op ) ( p, count ) , sea r el valor de retorno.
-
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) |