How fmtlib Implements C++20 std::format and C++23 std::print Support
fmtlib serves as the reference implementation for C++20 std::format and C++23 std::print, exposing these standard interfaces through include/fmt/format.h and include/fmt/core.h while providing high-performance output buffering and compile-time format string validation.
The fmtlib/fmt repository forms the foundation of modern C++ text formatting as the direct predecessor to the C++20 <format> and C++23 <print> standard library headers. Understanding how fmtlib supports C++20 std::format and C++23 std::print reveals the architectural decisions that enable sub-second formatting of millions of records without iostream overhead.
Architecture of C++20 std::format Implementation
fmtlib defines the API that standardized into C++20 std::format, implementing the format string syntax and argument handling that became the international standard.
The format() Function Template
In include/fmt/format.h, the primary entry point fmt::format() provides the same interface as std::format():
template <typename... Args>
FMT_INLINE auto format(format_string<Args...> fmt, Args&&... args) -> std::string {
return vformat(fmt, fmt::make_format_args(args...));
}
This implementation delegates to type-erased formatting via vformat() defined in the same header, minimizing binary bloat while preserving type safety through the format_string concept-like constraint.
Compile-Time Format String Validation
fmtlib supports C++20 consteval format string parsing through mechanisms in include/fmt/compile.h. The library parses format specifiers at compile time when possible, validating argument types against format string placeholders before runtime using the FMT_COMPILE macro.
C++23 std::print Implementation in fmtlib
The C++23 std::print functionality draws directly from fmtlib's existing fmt::print implementation, which has supported direct stdout output since version 5.0.
High-Performance Output Buffering
In include/fmt/core.h, fmt::print() avoids iostreams entirely and delegates to vprint():
template <typename... Args>
FMT_INLINE void print(format_string<Args...> fmt, Args&&... args) {
return detail::is_utf8() ? vprint(std::stdout, fmt, fmt::make_format_args(args...))
: vprint(std::stdout, fmt, fmt::make_format_args(args...));
}
The actual output buffering occurs in src/format.cc, where vprint() uses std::fwrite() for block writes rather than character-by-character output, achieving 5-10x faster performance than std::ostream.
Unicode and Locale Handling
fmtlib's print support handles UTF-8 validation through detail::is_utf8() checks in include/fmt/format.h, ensuring correct behavior for multibyte characters without relying on global C++ locales.
Type Erasure and Argument Storage
At the heart of both std::format and std::print compatibility lies fmtlib's dynamic argument store. The format_args type alias in include/fmt/core.h implements the type erasure required by the C++20 standard:
// From include/fmt/core.h
using format_args = basic_format_args<format_context>;
This type erasure allows vformat() and vprint() to process arguments without template instantiation for every unique parameter combination, reducing compile times and binary size while maintaining the static type safety of the outer API.
Integration with Standard Library Features
While fmtlib predates standardization, it detects standard library availability through __cpp_lib_format. In include/fmt/std.h, the library provides formatters for standard types like std::optional, std::variant, and std::thread::id, ensuring feature parity with C++23 standard library extensions.
When compiled with C++20 or later, fmtlib remains fully compatible with std::format output iterators and std::format_to_n algorithms, allowing seamless interoperability between fmt::format and std::format in the same codebase.
Summary
- fmtlib originates std::format: The C++20
<format>header standardizes the API first implemented ininclude/fmt/format.hwith function templates likefmt::format()andfmt::vformat(). - C++23 print performance: fmtlib's
fmt::print()ininclude/fmt/core.husesstd::fwrite()buffering viavprint()insrc/format.cc, delivering the high-performance output that became C++23std::print. - Type erasure architecture: Both standards rely on fmtlib's
format_argstype erasure pattern to minimize template bloat while preserving compile-time format string validation. - Cross-version compatibility: Headers like
include/fmt/std.hextend support to standard library types, maintaining API consistency across C++17, C++20, and C++23 compilation modes.
Frequently Asked Questions
Does fmtlib provide std::format in the std namespace?
No, fmtlib implements fmt::format in its own namespace as the reference implementation. Standard library vendors provide std::format by adopting fmtlib's interface. You should include <fmt/format.h> and use fmt::format directly, which remains compatible with the standard specification and works on pre-C++20 compilers.
How does fmt::print differ from C++23 std::print?
fmt::print has been available since fmtlib 5.0 and implements the same formatting specification as C++23 std::print. The primary difference is namespace placement—fmt::print resides in the fmt namespace and supports older C++ standards, whereas std::print requires C++23. Both use the same efficient buffering strategy via vprint() in src/format.cc.
Can I migrate from fmtlib to standard library format incrementally?
Yes, fmtlib maintains API compatibility with C++20 std::format. You can replace fmt::format with std::format calls incrementally, as both support the same format string syntax and argument handling. However, fmtlib offers additional features like named arguments and compile-time format compilation that remain unavailable in standard C++ through C++23.
Why use fmtlib instead of native C++23 std::print?
fmtlib provides broader compiler support (C++11 and later) and additional features like runtime format string compilation via FMT_COMPILE macros, color output via fmt::print with text styling, and Windows console UTF-8 handling. The library also typically delivers faster compile times than standard library <format> headers on older compilers while maintaining binary compatibility through src/format.cc.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →