项目简介
fmt 是开源 C++ 格式化库,实现了 C++20 std::format 与 C++23 std::print。它提供类似 Python 的格式语法与位置参数,支持自定义类型、Unicode、chrono 与范围。库具有类型安全、高性能,并可选单头文件模式。
README 预览
\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 p常见问题 (5)
故障排除为什么 {fmt} 会在 `{:?}` 和 vector/range 输出中将较新的 emoji 和 CJK 字符转义为 \Uxxxxxxxx,该如何修复?
发生这种情况是因为 fmt::detail::is_printable 是根据 Unicode 13.0 数据生成的。Unicode 14.0–17.0 中新增的码点(例如 🫠 U+1FAE0 和 CJK Extensions H/I/J)被错误地归类为未分配(Cn),因此会被转义。请将 {fmt} 更新到包含 Update is_printable to Unicode 17.0 修复的发行版或提交。如果你维护的是 fork,请运行 python3 support/printable.py,从 Unicode 17.0.0 的 UnicodeData.txt 重新生成该表——如果脚本中固定了 Unicode 版本/数据 URL,请一并更新——然后替换生成的 is_printable 代码并重新构建。之后,fmt::print("{:?}\n", "🫠") 将输出 "🫠" 而不是 "\U0001fae0"。
故障排除如何修复使用 /W4 编译时 fmt/ranges.h 中出现的 MSVC 警告 C4702(不可达代码)?
这是一个已知的 MSVC 误报,由 fmt 12.2.0 的 range formatter 触发。请修补 include/fmt/ranges.h 中的 formatter() 构造函数,使 set_brackets() 位于 else 分支中:
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, '}'>{});
}
然后重新构建。作为临时变通方法,可以使用 #pragma warning(disable: 4702) 对该第三方头文件禁用此警告,或者使用 /wd4702 选项编译,但首选做法是应用该补丁,或升级到包含此修复的 fmt 版本。
故障排除如何修复无法检出由 release tag 所引用的 commit 的 Git submodule?
在更新所有子模块之前,先获取其中的标签:
git submodule foreach --recursive 'git fetch --tags'
git submodule update --recursive
当子模块指向的某个标签的提交无法从任何已配置的分支访问到时,就需要执行此操作。永久的解决方法是让维护者在受维护的分支上为该版本打上标签,或者创建一个单独的发布分支。
故障排除当 `FMT_USE_LOCALE=0` 时,如何修复 fmt 的 `{:L}` 说明符,使其使用逗号分组或全局 locale?
这是一个 fmt 的 bug:在禁用 locale 支持的情况下,{:L} 对整数会被忽略,对浮点值则使用硬编码的逗号作为回退,并且某些 chrono 格式化器会查询 std::locale()(即全局 locale)。请升级到包含 issue #4941 修复的 fmt 版本,或应用上游更改 "Use classic locale grouping without locale support" 和 "Don't require std::locale in chrono.h when FMT_USE_LOCALE is 0"。修复后,L 会被接受,但使用 classic/C locale 语义:fmt::format("{:L}", 1234567) 仍为 1234567,而 fmt::format("{:L}", 1234.5) 返回 1234.5,不进行逗号分组。在包含 fmt 之前定义该宏,例如在 C++ 中:在 #include <fmt/...> 之前添加 #define FMT_USE_LOCALE 0;或在 CMake 中:target_compile_definitions(my_target PRIVATE FMT_USE_LOCALE=0),然后重新构建。在受影响的版本上,作为变通方法,可以从格式字符串中移除 L。如果需要特定于 locale 的数字或 chrono 名称,请使用 FMT_USE_LOCALE=1 构建,并将所需的 std::locale 显式传递给 fmt::format。
故障排除如何修复 Clang 15–20 在将 fmt::format_as 用于派生自 std::array 的类型时出现的段错误?
该类型既是一个 range(因为它继承了 std::array),又具有 format_as 重载,因此 {fmt} 的 range formatter 与 format_as 支持之间存在歧义。Clang 没有报告该歧义,而是直接崩溃。通过为你的类型提供显式的 fmt::formatter 特化来解决此问题:
#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);
}
};
或者,如果你希望使用默认的 range 格式化,可以移除 format_as;或者使用组合而不是公有继承 std::array,这样该类型就不会被识别为 range。Clang 的段错误本身是 Clang 15 到 20 中的一个编译器 bug,但该歧义才是根本的源代码问题。