Skip to main content

The format function family

One formatting engine, several entry points that differ only in where the characters land — pick the right one by destination, not by taste.

The family

FunctionWrites toReturnsAllocates
fmt::formatNew std::stringThe stringYes, unless small-string-optimized
fmt::printstdoutvoidNo
fmt::print(FILE*, ...)Given C streamvoidNo
fmt::format_toAny output iteratorThe iterator, past the last charDepends on the iterator
fmt::format_to_nFixed-size bufferIterator + count that would have been writtenNo
fmt::formatted_sizeNothingThe size the output would needNo
fmt::vformat / fmt::vformat_toString / iteratorSame as format/format_toSame as format/format_to

format

The simple case: build a std::string and hand it back.

std::string s = fmt::format("{}={}", key, value);

print

Writes directly to a stream with no intermediate string allocation.

fmt::print is faster than std::cout with fmt::format — it skips the string

fmt::print("{}\n", x) formats straight into the destination's buffer. std::cout << fmt::format("{}\n", x) allocates a std::string, then copies it into the stream. If the only thing you were going to do with the formatted string is print it, use fmt::print.

format_to

Appends through an output iterator instead of returning a fresh string — useful when you're building up a larger buffer piece by piece.

std::string out;
fmt::format_to(std::back_inserter(out), "[{}] ", timestamp);
fmt::format_to(std::back_inserter(out), "{}: {}\n", level, message);

See Output iterators and format_to for the full range of iterators this works with, including fixed buffers and custom sinks.

format_to_n

Writes into a fixed-size buffer, stopping at the bound, and reports both the iterator and the total size the write would have needed.

format_to_n truncates and reports the size it would have needed — check the returned size before trusting the buffer
char buf[16];
auto result = fmt::format_to_n(buf, sizeof(buf), "{}", long_string);
if (result.size > sizeof(buf)) {
// truncated — buf holds only the first sizeof(buf) characters
}

formatted_size

Measures the output length without producing it, so you can allocate exactly once and then format directly into that allocation instead of letting format/format_to grow a buffer incrementally.

size_t n = fmt::formatted_size("{}", value);
std::string s(n, '\0');
fmt::format_to(s.data(), "{}", value);

vformat and type erasure

fmt::vformat/fmt::vformat_to take a type-erased argument list built with fmt::make_format_args, rather than a variadic parameter pack. They exist so a function can accept "a format string and some arguments" without instantiating a fresh template for every distinct combination of argument types at every call site — useful in a logging wrapper that's included everywhere. The cost is a lifetime caveat: the erased argument list only refers to its arguments, so it must not outlive the call that consumes it. See Common pitfalls for the failure mode.

See also