概要
fmt はオープンソースの C++ フォーマットライブラリで、C++20 の std::format と C++23 の std::print を実装しています。Python 風のフォーマット構文と位置引数を提供し、カスタム型、Unicode、chrono、ranges をサポートしています。このライブラリは型安全で高性能であり、オプションで単一ヘッダーファイルモードも利用できます。
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 pFAQ (5)
トラブル対応なぜ {fmt} は `{:?}` や vector/range の出力で新しい絵文字や CJK 文字を \Uxxxxxxxx にエスケープするのですか?また、どうすれば修正できますか?
これは、fmt::detail::is_printable が Unicode 13.0 のデータから生成されているために発生します。Unicode 14.0〜17.0 で追加されたコードポイント(🫠 U+1FAE0 や CJK 拡張 H/I/J など)は、誤って未割り当て(Cn)として分類されるため、エスケープされてしまいます。Update is_printable to Unicode 17.0 の修正を含むリリースまたはコミットへ {fmt} を更新してください。フォークを保守している場合は、python3 support/printable.py を実行して Unicode 17.0.0 の UnicodeData.txt からテーブルを再生成します(スクリプトの Unicode バージョンやデータ URL が固定されている場合はそれらを更新してください)。その後、生成された is_printable のコードを置き換えてリビルドしてください。これにより、fmt::print("{:?}\n", "🫠") は "\U0001fae0" ではなく "🫠" を出力するようになります。
トラブル対応/W4 でコンパイルする際に fmt/ranges.h で発生する MSVC 警告 C4702(到達不能コード)を修正する方法
これは、fmt 12.2.0 の range フォーマッターによって引き起こされる、既知の MSVC の誤検出です。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 リリースにアップグレードすることを推奨します。
トラブル対応リリースタグが参照しているコミットをチェックアウトできないGitサブモジュールを修正するには、どうすればよいですか?
サブモジュールを更新する前に、すべてのサブモジュールのタグを取得します:
git submodule foreach --recursive 'git fetch --tags'
git submodule update --recursive
これは、サブモジュールが、設定されているどのブランチからも到達できないコミットを持つタグを指している場合に必要です。恒久的な解決策は、メンテナーがメンテナンスされているブランチ上でリリースにタグを付けるか、専用のリリースブランチを作成することです。
トラブル対応FMT_USE_LOCALE=0 のときに fmt の {:L} 指定子がカンマによるグルーピングまたはグローバルロケールを使うように修正するにはどうすればよいですか?
これは fmt のバグでした。ロケールサポートが無効になっていると、{:L} は整数に対しては無視され、浮動小数点値に対してはハードコードされたカンマへのフォールバックが使われ、一部の chrono フォーマッタはグローバルロケールである std::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 は受け付けられますが、クラシック/C ロケールのセマンティクスが使用されます: 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 を削除してください。ロケール固有の数値や chrono の名前が必要な場合は、FMT_USE_LOCALE=1 でビルドし、目的の std::locale を fmt::format に明示的に渡してください。
トラブル対応std::array から派生した型に対して fmt::format_as を使用した際に発生する Clang 15〜20 のセグメンテーションフォルトの修正方法
この型は std::array を継承しているため range であると同時に format_as オーバーロードも持っているため、{fmt} の range フォーマッタと 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 を public 継承する代わりにコンポジションを使用して、その型が range として認識されないようにしてください。Clang のセグフォルト自体は Clang 15 から 20 におけるコンパイラのバグですが、根本的な原因となるソースの問題はこの曖昧さです。