fmt
Código de fmt: por qué format_to_n devuelve más de lo que escribe
Lee los traits de salida limitada para separar tamaño total, iterador final, ausencia de terminador nulo y truncamiento de bytes UTF-8.
Qué aprenderás
- Separa salida almacenada y salida lógica
- Usa un centinela para revelar el contrato
- Delimita lo que prueba cada ejemplo
Antes de empezar
- Valores, referencias, cadenas y destinos de construcción en C++
- Distinguir expectativas documentadas de resultados medidos
Traza comportamientos concretos de fmt y elige una integración con límites explícitos de salida, vida útil y verificación.
Conclusiones clave
- result.size describe el resultado completo, no la cantidad almacenada.
- format_to_n no añade terminador nulo.
- Un límite de escritura en bytes no es una vista Unicode segura ni un límite de CPU.
Separa salida almacenada y salida lógica
format_to_n devuelve un format_to_n_result con un iterador y el tamaño completo sin truncar. En core.h, vformat_to_n crea un búfer iterador con fixed_buffer_traits, formatea y devuelve buf.out() junto con buf.count(). La distinción es intencional: un destino de cuatro bytes no implica que el valor formateado mida cuatro bytes.
El objeto traits mantiene un límite de escritura y un contador acumulado. Su función limit suma todo el tamaño del bloque entrante a count_, pero solo devuelve la parte permitida por el espacio restante. En la especialización de puntero, al agotarse el destino directo se utiliza almacenamiento interno y continúa la ruta de formato y cómputo.
Usa un centinela para revelar el contrato
La prueba upstream de format_to_n escribe el entero 12345 en tres posiciones de una matriz de cuatro caracteres, dejando un centinela en la cuarta. Espera size 5, un iterador avanzado tres posiciones y los cuatro bytes 123x. La API documenta que no añade terminador nulo; ese resultado no justifica pasar la matriz a un consumidor de cadenas C.
Un límite cero permite devolver la longitud lógica sin escribir en el destino. Un límite positivo tampoco garantiza un límite de grafema Unicode. En datos UTF-8 basados en char, escribir solo dos bytes de un carácter de tres puede dejar una secuencia incompleta. Una vista previa necesita su propia política de truncamiento consciente de la codificación.
Delimita lo que prueba cada ejemplo
El ejemplo C++ muestra la API pública con centinela y aserciones exactas del iterador. La prueba editorial complementaria incluye límite cero, una entrada UTF-8 de tres bytes y un error trasladado a ejecución. Son casos pequeños que detectan supuestos incorrectos sin consumir memoria masiva ni depender de entradas remotas.
Otra prueba independiente en JavaScript solo modela el cómputo por bloques; no es un analizador C++ ni un sustituto nativo de fmt. Mantén esa diferencia al explicar resultados. Ni el modelo ni una prueba nativa acotada establecen rendimiento con anchuras enormes, formatters propios, excepciones desactivadas o cualquier iterador posible.
Pasos de implementación
- 1
Inicializa el búfer con un centinela visible.
- 2
Formatea un valor que supere el límite.
- 3
Comprueba iterador, tamaño total y centinela por separado.
- 4
Añade casos cero y multibyte sin tratar el prefijo como texto válido automáticamente.
Ejemplo para copiar
#include <fmt/format.h>
#include <cassert>
#include <string>
int main() {
char out[4] = {'x', 'x', 'x', 'x'};
const auto result = fmt::format_to_n(out, 3, "{}", 12345);
assert(result.out == out + 3);
assert(result.size == 5);
assert(std::string(out, 4) == "123x");
}Preguntas frecuentes
¿Por qué escribir tres caracteres devuelve tamaño cinco?
El campo size cuenta el resultado completo. El iterador devuelto identifica la parte realmente escrita.
¿Puedo llamar strlen sobre esa salida?
No según ese contrato. La API no añade terminador; usa una longitud conocida o reserva y escribe explícitamente un terminador en tu envoltorio.
Fuentes
- include/fmt/core.hFuente verificada 2026-09-08
- test/format-test.ccFuente verificada 2026-09-08
- doc/syntax.mdFuente verificada 2026-09-08