C++開発を加速するfmtライブラリ:型安全で高速な文字列フォーマット術
fmt は、C++ での文字列フォーマットをより安全で、高速で、使いやすくするモダンなライブラリです。従来の C スタイルの printf や、C++ 標準ライブラリのストリーム (<<) と比較して、次のような点が特に役立ちます。
printf はフォーマット指定子 (%d, %s など) と引数の型が一致しないと、未定義動作(Undefined Behavior)を引き起こす可能性があります。fmt はテンプレートとコンパイル時のチェックを利用しているため、このような型不一致によるバグをコンパイル段階で発見できます。これにより、ランタイムでの予期せぬクラッシュを防ぎ、デバッグの時間を大幅に削減できます。
ストリーム (std::cout << ...) は柔軟性が高い反面、オーバーヘッドが大きくなりがちです。fmt は、高いパフォーマンスを出すために最適化されており、特に大量のログ出力や、パフォーマンスが重視されるアプリケーションで威力を発揮します。
Python の str.format() のような分かりやすい構文を採用しています。位置引数や名前付き引数を使ったり、特定のフォーマット(小数点以下の桁数、ゼロパディングなど)を指定したりするのが簡単です。
fmt は単一のヘッダーファイルとして利用できるため、プロジェクトへの導入が非常に簡単です。
fmt/core.h をダウンロードして、インクルードパスに追加するだけで使えます。
CMake を使っているプロジェクトなら、add_subdirectory() で追加するか、find_package() で見つけるのが一般的です。
# CMakeLists.txt の例
# GitHub から直接取得する場合
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.1.1 # バージョンは適宜変更
)
FetchContent_MakeAvailable(fmt)
# リンクする場合
target_link_libraries(your_project_name PRIVATE fmt::fmt)
C++20 からは std::format が標準化され、fmt の機能が取り込まれました。fmt は、それ以前の C++ バージョンでも同じようなモダンなフォーマット機能を提供します。
#include <iostream>
#include <fmt/core.h>
int main() {
// 従来のやり方
int value = 42;
std::cout << "The answer is: " << value << std::endl;
// fmt を使ったやり方
fmt::print("The answer is: {}\n", value);
return 0;
}
{} を使うことで、引数の順番を指定せずに済みます。
#include <fmt/core.h>
#include <string>
int main() {
std::string name = "Taro";
int age = 30;
// 引数の順序を変えてもOK
fmt::print("Hello, {}! You are {} years old.\n", name, age);
fmt::print("You are {} years old, {}!\n", age, name);
// 位置引数を使うこともできる
fmt::print("Hello, {0}! You are {1} years old.\n", name, age);
fmt::print("You are {1} years old, {0}!\n", name, age);
return 0;
}
小数点以下の桁数指定や、ゼロパディング、アライメントなども簡単にできます。
#include <fmt/core.h>
int main() {
double pi = 3.1415926535;
// 小数点以下2桁まで
fmt::print("Pi is approximately {:.2f}\n", pi); // => Pi is approximately 3.14
// ゼロパディングと幅指定
int number = 7;
fmt::print("The number is {:0>5d}\n", number); // => The number is 00007
// 16進数表示
int color_code = 255;
fmt::print("The color code is 0x{:X}\n", color_code); // => The color code is 0xFF
return 0;
}