{fmt}は、C stdio および C++ iostream に代わる高速かつ安全な代替手段を提供するオープンソースの書式設定ライブラリです。
このプロジェクトが気に入っていただけましたら、ウクライナ戦争の犠牲者を支援する基金 (https://www.stopputin.net/) への寄付をご検討ください。
ドキュメント
チートシート
Q&A: fmt タグを使用して StackOverflow で質問します。
コンパイラー エクスプローラーで {fmt} を試してください。
ローカリゼーションのための位置引数を備えたシンプルな形式の API
C++20 std::format および C++23 std::print の実装
Python の形式に似た形式文字列構文
Dragonbox アルゴリズムを使用した正しい丸め、短さ、ラウンドトリップを保証する高速 IEEE 754 浮動小数点フォーマッタ
ポータブル Unicode サポート
位置引数の POSIX 拡張機能を含む安全な printf 実装
拡張性: ユーザー定義型のサポート
高パフォーマンス: (s)printf
、iostreams、 to_string
、 to_chars
の一般的な標準ライブラリ実装より高速です。「速度テスト」と「1 秒あたり 1 億の整数を文字列に変換する」を参照してください。
core.h
、 format.h
、 format-inl.h
の 3 つのファイルだけで構成される最小構成のソース コードとコンパイルされたコードの両方の点でコード サイズが小さい。 「コンパイル時間とコードの肥大化」を参照してください。
信頼性: ライブラリには広範なテストのセットがあり、継続的にファジングされています。
安全性: ライブラリは完全にタイプセーフであり、フォーマット文字列のエラーはコンパイル時に報告でき、自動メモリ管理によりバッファ オーバーフロー エラーが防止されます。
使いやすさ: 小規模な自己完結型コード ベース、外部依存関係なし、寛容な MIT ライセンス
プラットフォーム間で一貫した出力による移植性と古いコンパイラのサポート
-Wall -Wextra -pedantic
などの高い警告レベルであっても、警告のないクリーンなコードベース
デフォルトでロケールに依存しない
FMT_HEADER_ONLY
マクロで有効になるオプションのヘッダーのみの構成
詳細については、ドキュメントを参照してください。
標準出力に出力(実行)
#include <fmt/core.h>int main() { fmt::print("Hello, world!n"); }
文字列をフォーマットする(実行)
std::string s = fmt::format("答えは {}.", 42);// s == "答えは 42"
位置引数を使用して文字列をフォーマットする(run)
std::string s = fmt::format("私は {0} よりも {1} になりたいです。", "right", "happy");// s == "正しいよりも幸せになりたいです。」
日付と時刻を印刷する(実行)
#include <fmt/chrono.h>int main() { auto now = std::chrono::system_lock::now(); fmt::print("日時: {}n"、現在); fmt::print("時刻: {:%H:%M}n"、現在); }
出力:
Date and time: 2023-12-26 19:10:31.557195597 Time: 19:10
コンテナーを印刷する(実行)
#include <vector>#include <fmt/ranges.h>int main() { std::vector<int> v = {1, 2, 3}; fmt::print("{}n", v); }
出力:
[1, 2, 3]
コンパイル時にフォーマット文字列をチェックする
std::string s = fmt::format("{:d}", "私は数字ではありません");
d
文字列に対して無効な形式指定子であるため、これにより C++20 ではコンパイル時エラーが発生します。
単一スレッドからファイルを書き込む
#include <fmt/os.h>int main() { auto out = fmt::output_file("guide.txt"); out.print("{}しないでください", "パニック"); }
これは、fprintf よりも 5 ~ 9 倍高速になる可能性があります。
色とテキストスタイルを指定して印刷する
#include <fmt/color.h>int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "こんにちは、{}!n", "world" ); fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | fmt::emphasis::underline, "Olá, {}!n", "Mundo"); fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, "你好{}!n", "世界"); }
Unicode をサポートする最新の端末での出力:
図書館 | 方法 | 実行時間、秒 |
---|---|---|
リブ | プリントフ | 0.91 |
libc++ | std::ostream | 2.49 |
{fmt} 9.1 | fmt::print | 0.74 |
ブーストフォーマット1.80 | ブースト::フォーマット | 6.26 |
フォリーフォーマット | 愚かさ::フォーマット | 1.87 |
{fmt} はベンチマークされたメソッドの中で最も高速で、 printf
よりも最大 20% 高速です。
上記の結果は、 clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT
を使用して macOS 12.6.1 上でtinyformat_test.cpp
ビルドし、3 回実行したうちの最良のものを取得することによって生成されました。テストでは、フォーマット文字列"%0.10f:%04d:%+g:%s:%p:%c:%%n"
または同等の文字列が 2,000,000 回入力され、出力が/dev/null
に送信されます。詳細については、ソースを参照してください。
{fmt} は、IEEE754 float
およびdouble
フォーマット (dtoa-benchmark) ではstd::ostringstream
およびsprintf
よりも最大 20 ~ 30 倍高速であり、double-conversion および Ryu よりも高速です。
format-benchmark のスクリプト blat-test.py は、重要なプロジェクトのコンパイル時間とコードの肥大化をテストします。 100 個の翻訳単位を生成し、それぞれでprintf()
またはその代替手段を 5 回使用して、中規模のプロジェクトをシミュレートします。結果の実行可能ファイルのサイズとコンパイル時間 (Apple Clang バージョン 15.0.0 (clang-1500.1.0.2.5)、macOS Sonoma、3 つのベスト) を次の表に示します。
最適化されたビルド (-O3)
方法 | コンパイル時間、秒 | 実行可能サイズ、KiB | ストリップサイズ、KiB |
---|---|---|---|
プリントフ | 1.6 | 54 | 50 |
IOストリーム | 25.9 | 98 | 84 |
fmt 83652df | 4.8 | 54 | 50 |
タイニーフォーマット | 29.1 | 161 | 136 |
ブーストフォーマット | 55.0 | 530 | 317 |
{fmt} はコンパイルが速く、呼び出しごとのバイナリ サイズの点でprintf
に匹敵します (このシステムの丸め誤差の範囲内)。
最適化されていないビルド
方法 | コンパイル時間、秒 | 実行可能サイズ、KiB | ストリップサイズ、KiB |
---|---|---|---|
プリントフ | 1.4 | 54 | 50 |
IOストリーム | 23.4 | 92 | 68 |
{fmt} 83652df | 4.4 | 89 | 85 |
タイニーフォーマット | 24.5 | 204 | 161 |
ブーストフォーマット | 36.4 | 831 | 462 |
libc
、 lib(std)c++
、およびlibfmt
すべて、書式設定関数のオーバーヘッドのみを比較するための共有ライブラリとしてリンクされています。 Boost Format はヘッダーのみのライブラリであるため、リンク オプションは提供されません。
ライブラリを構築して単体テストを実行する方法については、「ライブラリの構築」を参照してください。
ベンチマークは別のリポジトリ format-benchmarks に存在するため、ベンチマークを実行するには、まずこのリポジトリのクローンを作成し、CMake で Makefile を生成する必要があります。
$ git clone --recursive https://github.com/fmtlib/format-benchmark.git $ cd format-benchmark $ cmake .
次に、速度テストを実行できます。
$ make speed-test
または膨満テスト:
$ make bloat-test
Clang-tidy v18 は、 printf
およびfprintf
の出現をfmt::print
に変換できる modernize-use-std-print チェックを提供します (そうするように構成されている場合)。 (デフォルトではstd::print
に変換されます。)
0 AD: 無料のオープンソース、クロスプラットフォームのリアルタイム ストラテジー ゲーム
AMPL/MP: 数学的プログラミング用のオープンソース ライブラリ
Apple の FoundationDB: オープンソースの分散型トランザクション キー/バリュー ストア
Aseprite: アニメーション スプライト エディターおよびピクセル アート ツール
AvioBook: 包括的な航空機運用スイート
Blizzard Battle.net: オンライン ゲーム プラットフォーム
Celestia: 空間のリアルタイム 3D 視覚化
Ceph: スケーラブルな分散ストレージ システム
ccache: コンパイラのキャッシュ
ClickHouse: 分析データベース管理システム
ContextVision: 医療画像ソフトウェア
Contour: 最新のターミナル エミュレーター
CUAUV: コーネル大学の自律型水中車両
Drake: 非線形力学システム (MIT) の計画、制御、および解析ツールボックス
Envoy: C++ L7 プロキシおよび通信バス (Lyft)
FiveM: GTA V 用の修正フレームワーク
fmtlog: ナノ秒単位のレイテンシを備えた高性能な fmtlib スタイルのロギング ライブラリ
Folly: Facebook オープンソース ライブラリ
GemRB: Bioware の Infinity Engine のポータブルなオープンソース実装
Grand Mountain Adventure: 美しいオープンワールドのスキー & スノーボード ゲーム
HarpyWar/pvpgn: 微調整を加えたプレイヤー vs プレイヤー ゲーム ネットワーク
KBEngine: オープンソースの MMOG サーバー エンジン
Keypirinha: Windows 用のセマンティック ランチャー
Kodi (旧 xbmc): ホームシアター ソフトウェア
Knuth: 高性能ビットコインフルノード
libunicode: 最新の C++17 Unicode ライブラリ
MariaDB: リレーショナル データベース管理システム
Microsoft Verona: 同時所有のための研究用プログラミング言語
MongoDB: 分散ドキュメント データベース
MongoDB Smasher: ランダム化されたデータセットを生成する小さなツール
OpenSpace: オープンソースの天体視覚化フレームワーク
PenUltima Online (POL): ほとんどの Ultima Online クライアントと互換性のある MMO サーバー
PyTorch: オープンソースの機械学習ライブラリ
quasardb: 分散型、高性能、連想型データベース
Quill: 非同期低遅延ロギング ライブラリ
QKW: ナビゲーションを簡素化し、複雑な複数行の端末コマンド シーケンスを実行するためのエイリアシングの一般化
redis-cerberus: Redis クラスター プロキシ
redpanda: C++ で書かれたミッションクリティカルなシステムの 10 倍高速な Kafka® 代替品
rpclib: 最新の C++ msgpack-RPC サーバーおよびクライアント ライブラリ
Salesforce Analytics Cloud: ビジネス インテリジェンス ソフトウェア
Scylla: 単一サーバー上で 1 秒あたり 100 万トランザクションを処理できる Cassandra 互換の NoSQL データ ストア
Seastar: 最新のハードウェア上の高性能サーバー アプリケーション用の高度なオープンソース C++ フレームワーク
spdlog: 超高速 C++ ロギング ライブラリ
Stellar: 金融プラットフォーム
Touch Surgery: 手術シミュレーター
TrinityCore: オープンソースの MMORPG フレームワーク
? userver フレームワーク: 豊富な抽象化セットとデータベース ドライバーを備えたオープンソースの非同期フレームワーク
Windows ターミナル: 新しい Windows ターミナル
もっと...
このライブラリを使用している他のプロジェクトをご存知の場合は、電子メールまたは問題を送信してお知らせください。
では、なぜさらに別の書式設定ライブラリを使用するのでしょうか?
このタスクを実行するためのメソッドは、printf ファミリの関数や iostream のような標準的なものから、Boost Format ライブラリや FastFormat ライブラリまで、たくさんあります。新しいライブラリを作成する理由は、私が見つけた既存のソリューションにはいずれも重大な問題があるか、必要な機能をすべて備えていなかったからです。
printf
の良い点は、C 標準ライブラリの一部として非常に高速ですぐに利用できることです。主な欠点は、ユーザー定義型をサポートしていないことです。 printf
も安全性の問題がありますが、GCC の __attribute__ ((format (printf, ...)) である程度緩和されています。 i18n に必要な位置引数をprintf
に追加する POSIX 拡張機能がありますが、これは C99 の一部ではなく、一部のプラットフォームでは利用できません。
iostream に関する主な問題は、次の例で最もよく分かります。
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "n";
これは printf に比べて多くの入力が必要です。
printf("%.2fn", 1.23456);
FastFormat の作者である Matthew Wilson は、これを「シェブロン地獄」と呼びました。 iostream は設計上、位置引数をサポートしていません。
良い点は、iostream はユーザー定義型をサポートしており、エラー処理は面倒ですが安全であることです。
これは、 printf
のような形式文字列と位置引数の両方をサポートする非常に強力なライブラリです。その主な欠点はパフォーマンスです。さまざまなベンチマークによると、ここで検討した他の方法よりもはるかに遅いです。 Boost Format には、過度のビルド時間と深刻なコード肥大化の問題もあります (ベンチマークを参照)。
これは、高速かつ安全で、位置引数を備えた興味深いライブラリです。ただし、これには重大な制限があると著者は述べています。
現在の設計に対応する見込みのない 3 つの機能は次のとおりです。
先頭のゼロ (またはその他のスペース以外の埋め込み)
8進数/16進数のエンコーディング
ランタイム幅/アライメント仕様
また、非常に大きく、STLSoft に大きく依存しているため、プロジェクトによっては使用が制限されすぎる可能性があります。
これは書式設定ライブラリではありませんが、完全を期すためにここに含めることにしました。 iostream としては、逐語的なテキストと引数が混在するという問題があります。このライブラリはかなり高速ですが、整数の書式設定では、Karma 独自のベンチマークで書式文字列コンパイルを行うfmt::format_to
よりも遅くなります。「1 秒あたり 1 億の整数を文字列に変換する」を参照してください。
{fmt} は MIT ライセンスに基づいて配布されます。
このドキュメントの「フォーマット文字列構文」セクションは、Python 文字列モジュールのドキュメントに基づいています。このため、ドキュメントは doc/python-license.txt で入手可能な Python Software Foundation ライセンスに基づいて配布されています。これは、{fmt} のドキュメントを配布する場合にのみ適用されます。
{fmt} ライブラリは、他の多くの人々の貢献により Victor Zverovich (vitaut) によって維持されています。名前の一部については、「貢献者とリリース」を参照してください。あなたの貢献がリストに掲載されていない場合、または間違って言及されている場合はお知らせください。修正させていただきます。
セキュリティ問題を報告するには、セキュリティ アドバイザリーでその問題を開示してください。
このプロジェクトは、ボランティアのチームによって合理的な努力に基づいて維持されています。そのため、一般に公開される前に修正に取り組むために少なくとも90日間の猶予を与えてください。