fmt
Libraryfmtlib/fmt
A modern C++ formatting library providing fast, safe alternatives to printf and iostreams.
Overview
fmt is an open-source C++ formatting library that implements C++20 std::format and C++23 std::print. It offers a Python-like format syntax with positional arguments, supports user-defined types, Unicode, chrono, and ranges. The library is type-safe, highly performant, and available as a header-only config.
README Preview
\n\n[](\nhttps://github.com/fmtlib/fmt/actions?query=workflow%3Alinux)\n[](\nhttps://github.com/fmtlib/fmt/actions?query=workflow%3Amacos)\n[](\nhttps://github.com/fmtlib/fmt/actions?query=workflow%3Awindows)\n[](\nhttps://issues.oss-fuzz.com/issues?q=title:fmt%20cc:victor.zverovich@gmail.com)\n[](\nhttps://www.bestpractices.dev/projects/8880)\n[](\nhttps://securityscorecards.dev/viewer/?uri=github.com/fmtlib/fmt)\n[](https://stackoverflow.com/questions/tagged/fmt)\n[](https://novaukraine.org/)\n\n**{fmt}** is an open-source formatting library providing a fast and safe\nalternative to C stdio and C++ iostreams.\n\n[Documentation](https://fmt.dev)\n\n[Cheat Sheets](https://hackingcpp.com/cpp/libs/fmt.html)\n\nQ&A: ask questions on [StackOverflow with the tag\nfmt](https://stackoverflow.com/questions/tagged/fmt).\n\nTry {fmt} in [Compiler Explorer](https://godbolt.org/z/8Mx1EW73v).\n\n# Features\n\n- Simple [format API](https://fmt.dev/latest/api/) with positional\n arguments for localization\n- Implementation of [C++20\n std::format](https://en.cppreference.com/w/cpp/utility/format) and\n [C++23 std::print](https://en.cppreference.com/w/cpp/io/print)\n- [Format string syntax](https://fmt.dev/latest/syntax/) similar\n to Python\'s\n [format](https://docs.python.org/3/library/stdtypes.html#str.format)\n- Fast IEEE 754 floating-point formatter with correct rounding,\n shortness and round-trip guarantees using the\n [Dragonbox](https://github.com/jk-jeon/dragonbox) algorithm\n- Portable Unicode support\n- Safe [printf\n implementation](https://fmt.dev/latest/api/#printf-api)\n including the POSIX extension for positional arguments\n- Extensibility: [support for user-defined\n types](https://fmt.dev/latest/api/#formatting-user-defined-types)\n- High performance: faster than common standard library\n implementations of `(s)printf`, iostreams, `to_string` and\n `to_chars`, see [Speed tests](#speed-tests) and [Converting a\n hundred million integers to strings pFAQ (5)
TroubleshootingWhy does {fmt} escape newer emoji and CJK characters as \Uxxxxxxxx in `{:?}` and vector/range output, and how do I fix it?
This occurs because fmt::detail::is_printable was generated from Unicode 13.0 data. Code points added in Unicode 14.0–17.0, such as 🫠 U+1FAE0 and CJK Extensions H/I/J, are incorrectly classified as unassigned (Cn) and therefore escaped. Update {fmt} to a release or commit containing the Update is_printable to Unicode 17.0 fix. If maintaining a fork, regenerate the table from Unicode 17.0.0 UnicodeData.txt by running python3 support/printable.py—updating the script’s Unicode version/data URL if it is pinned—and replace the generated is_printable code, then rebuild. Afterward, fmt::print("{:?}\n", "🫠") outputs "🫠" instead of "\U0001fae0".
TroubleshootingHow to fix MSVC warning C4702 (unreachable code) in fmt/ranges.h when compiling with /W4?
This is a known MSVC false positive triggered by fmt 12.2.0's range formatter. Patch the formatter() constructor in include/fmt/ranges.h so set_brackets() is in an else branch:
FMT_CONSTEXPR formatter() {
if FMT_CONSTEXPR20 (range_format_kind<R, Char>::value != range_format::set)
return;
else
range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
detail::string_literal<Char, '}'>{});
}
Then rebuild. As a temporary workaround, you can disable the warning for the third-party header with #pragma warning(disable: 4702) or compile with /wd4702, but applying the patch or upgrading to a fmt release containing the fix is preferred.
TroubleshootingHow do I fix a Git submodule that cannot check out a commit referenced by a release tag?
Fetch tags in all submodules before updating them:
git submodule foreach --recursive 'git fetch --tags'
git submodule update --recursive
This is needed when the submodule points to a tag whose commit is not reachable from any configured branch. A permanent fix is for the maintainer to tag the release on a maintained branch or create a separate release branch.
TroubleshootingHow do I fix fmt's `{:L}` specifier using comma grouping or the global locale when `FMT_USE_LOCALE=0`?
This was an fmt bug: with locale support disabled, {:L} was ignored for integers, used a hard-coded comma fallback for floating-point values, and some chrono formatters consulted std::locale(), which is the global locale. Update to an fmt release containing the fixes for issue #4941, or apply the upstream changes "Use classic locale grouping without locale support" and "Don't require std::locale in chrono.h when FMT_USE_LOCALE is 0". After the fix, L is accepted but uses classic/C-locale semantics: fmt::format("{:L}", 1234567) remains 1234567, and fmt::format("{:L}", 1234.5) returns 1234.5 without comma grouping. Define the macro before including fmt, for example with C++: #define FMT_USE_LOCALE 0 before #include <fmt/...>, or CMake: target_compile_definitions(my_target PRIVATE FMT_USE_LOCALE=0), then rebuild. On affected versions, remove L from format strings as a workaround. If you need locale-specific numbers or chrono names, build with FMT_USE_LOCALE=1 and pass the desired std::locale explicitly to fmt::format.
TroubleshootingHow to fix Clang 15–20 segmentation fault when using fmt::format_as with a type derived from std::array?
The type is both a range because it inherits std::array and has a format_as overload, so {fmt}'s range formatter and format_as support are ambiguous. Clang crashes instead of reporting the ambiguity. Resolve it by providing an explicit fmt::formatter specialization for your type:
#include <fmt/format.h>
template <>
struct fmt::formatter<Sha256Hash> : fmt::formatter<std::string>
{
auto format(const Sha256Hash& h, fmt::format_context& ctx) const
{
return fmt::formatter<std::string>::format(format_as(h), ctx);
}
};
Alternatively, remove format_as if you want the default range formatting, or use composition instead of publicly inheriting std::array so the type is not recognized as a range. The Clang segfault itself is a compiler bug in Clang 15 through 20, but the ambiguity is the underlying source issue.