{fmt} 库 API 完全指南:从基础格式化到 C++20 兼容与二进制优化
【免费下载链接】fmtA modern formatting library项目地址: https://gitcode.com/GitHub_Trending/fm/fmt
导读
本文是 {fmt} 现代 C++ 格式化库的 API 权威参考,系统梳理了fmt/base.h基础 API、fmt/format.h完整格式化 API,以及 ranges、chrono、std、enum、compile、color、os、ostream、args、printf、xchar 等十余个功能头文件的核心接口与用法。你将掌握格式化字符串语法、用户自定义类型的两种扩展方式、编译期检查与类型擦除、命名参数、动态参数列表、宽字符支持,以及通过 CMake 选项与预处理器宏裁剪库体积的完整配置方案。文中所有结论均以当前仓库源码为据,可放心用于工程实践。
{fmt} 的 API 由以下组件构成(均位于include/fmt/目录):
fmt/base.h:基础 API,提供char/UTF-8 的主要格式化函数,带 C++20 编译期检查,依赖最少;fmt/format.h:fmt::format等完整格式化函数及 locale 支持;fmt/ranges.h:range 与 tuple 的格式化;fmt/chrono.h:日期时间格式化;fmt/std.h:标准库类型的 formatter;fmt/enum.h:注解枚举的格式化;fmt/compile.h:格式字符串编译(编译期格式化);fmt/color.h:终端颜色与文本样式;fmt/os.h:系统 API(文件输出、Windows 错误);fmt/ostream.h:std::ostream支持;fmt/args.h:动态参数列表;fmt/printf.h:类型安全的printf;fmt/xchar.h:可选的wchar_t支持。
所有函数与类型都位于命名空间fmt中,所有宏都以FMT_为前缀。
C++ Module API
如果使用 C++ 模块(module)方式构建 {fmt},则无需逐个 include 上述头文件,直接用一条import fmt;语句即可。除此之外,下文列出的所有功能保持不变。从仓库的CMakeLists.txt可以看出,{fmt} 同时维护了传统的头文件/静态库构建与模块构建路径,模块方式在优化构建下可将应用代码编译时间降低约 27%(详见 README.md 中的编译时间对比表)。
基础 API(fmt/base.h)
fmt/base.h定义基础 API,为char/UTF-8 提供主要格式化函数,并带 C++20 编译期检查。该头文件包含依赖极少,利于缩短编译时间。需要注意:只有在以库方式(默认方式)使用 {fmt} 时,单独包含fmt/base.h才有收益,在 header-only 模式下并不明显。
fmt/base.h为以下类型提供了内置的formatter特化:
int、long longunsigned、unsigned long longfloat、double、long doubleboolcharconst char*、fmt::string_viewconst void*
这些函数使用的格式字符串语法与 Python 的str.format类似,接受fmt和args两个参数:
- fmt是包含字面文本与花括号
{}包围的替换字段的格式字符串,字段会被替换为格式化后的参数。fmt::format_string是一种可从字符串字面量或constexpr字符串隐式构造、并在 C++20 下编译期检查的格式字符串类型;若要传入运行时格式字符串,需要用fmt::runtime包裹; - args是要被格式化的对象列表。
I/O 错误(除非另行说明)以std::system_error异常的形式上报。
基础 API 的核心函数包括:
print(format_string<T...>, T&&...):向标准输出打印;print(FILE*, format_string<T...>, T&&...):向指定FILE*打印;println(format_string<T...>, T&&...)与println(FILE*, ...):带换行的打印;format_to(OutputIt&&, format_string<T...>, T&&...):格式化为迭代器输出;format_to_n(OutputIt, size_t, format_string<T...>, T&&...):限定最大输出长度的格式化,返回format_to_n_result(包含迭代器与写入字符数);formatted_size(format_string<T...>, T&&...):返回格式化结果的字符数,不实际输出。
在README.md的入门示例中,仅包含fmt/base.h即可完成fmt::print("Hello, world!\n");而fmt::format("The answer is {}.", 42)需要包含fmt/format.h。格式化还支持位置参数,例如fmt::format("I'd rather be {1} than {0}.", "right", "happy")输出I'd rather be happy than right.。
格式化用户自定义类型
{fmt} 为大量标准 C++ 类型提供了 formatter(range/tuple 见fmt/ranges.h,日期时间见fmt/chrono.h,其余标准库类型见fmt/std.h)。让一个自定义类型可格式化有两种方式:提供format_as函数,或特化formatter结构体模板。非 void 指针类型的格式化是被有意禁止的,任何扩展 API 都无法让它们可格式化。
方式一:format_as
当你想让自定义类型“以另一种类型的格式规格”被格式化时,使用format_as。该函数接收你的类型对象,返回一个可格式化类型的对象,且必须定义在你的类型所在命名空间中:
#include <fmt/format.h> namespace kevin_namespacy { enum class film { house_of_cards, american_beauty, se7en = 7 }; auto format_as(film f) { return fmt::underlying(f); } } int main() { fmt::print("{}\n", kevin_namespacy::film::se7en); // 输出: 7 }注意:format_as不能用于同时匹配另一个formatter特化(如 range formatter)的类型,否则特化会产生歧义。此时应尽可能禁用冲突的特化,或改为显式提供formatter特化。
方式二:特化formatter
特化更复杂,但能完全控制解析与格式化过程。推荐的做法是通过继承或组合复用现有 formatter,这样无需自己实现标准格式规格。例如为枚举color定义基于formatter<string_view>的 formatter:
// color.h: #include <fmt/base.h> enum class color {red, green, blue}; template <> struct fmt::formatter<color>: formatter<string_view> { // parse 从 formatter<string_view> 继承。 auto format(color c, format_context& ctx) const -> format_context::iterator; };// color.cc: #include "color.h" #include <fmt/format.h> auto fmt::formatter<color>::format(color c, format_context& ctx) const -> format_context::iterator { string_view name = "unknown"; switch (c) { case color::red: name = "red"; break; case color::green: name = "green"; break; case color::blue: name = "blue"; break; } return formatter<string_view>::format(name, ctx); }注意formatter<string_view>::format定义在fmt/format.h中,因此源文件必须包含该头。由于parse继承自formatter<string_view>,它会识别所有字符串格式规格,例如:
fmt::format("{:>10}", color::blue)将返回" blue"。
formatter 的一般形态如下:
template <> struct fmt::formatter<T> { // 解析格式规格并存储到 formatter 中。 // // [ctx.begin(), ctx.end()) 是一个(可能为空的)字符区间,包含从待解析 // 的格式规格开始的格式字符串片段,例如在 // // fmt::format("{:f} continued", ...); // // 中区间内容为 "f} continued"。formatter 应解析到 '}' 或区间末尾, // 本例中应解析 'f' 规格并返回指向 '}' 的迭代器。 constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator; // 用解析得到的格式规格格式化 value,并写入 ctx.out()。 auto format(const T& value, format_context& ctx) const -> format_context::iterator; };官方建议至少支持作用于整个对象的 fill、align、width,且语义与标准 formatter 一致。也可以为类层次编写 formatter——利用模板特化 +std::enable_if_t约束基类,例如在demo.h中定义struct A与struct B : A,再通过fmt::formatter<T, std::enable_if_t<std::is_base_of_v<A, T>, char>> : fmt::formatter<std::string>统一格式化整个继承体系,fmt::print("{}", a)(其中A& a = b)输出B。
同时提供formatter特化与format_as重载是不允许的。
编译期检查
在支持 C++20consteval的编译器上,编译期格式字符串检查默认开启;旧编译器可以使用fmt/format.h中定义的FMT_STRING宏(见下文“Legacy 编译期检查”)。未使用的参数是允许的,这与 Python 的str.format和普通函数一致。
例如,fmt::format("{:d}", "I am not a number")在 C++20 下会编译失败,因为d对字符串是无效的格式规格(见 README.md 的示例)。
类型擦除(Type Erasure)
利用fmt::format_string与类型擦除,可以编写自己的带编译期检查、且二进制体积很小的格式化函数:
#include <fmt/format.h> void vlog(const char* file, int line, fmt::string_view fmt, fmt::format_args args) { fmt::print("{}: {}: {}", file, line, fmt::vformat(fmt, args)); } template <typename... T> void log(const char* file, int line, fmt::format_string<T...> fmt, T&&... args) { vlog(file, line, fmt, fmt::make_format_args(args...)); } #define MY_LOG(fmt, ...) log(__FILE__, __LINE__, fmt, __VA_ARGS__) MY_LOG("invalid squishiness: {}", 42);关键点在于vlog不依赖参数类型,与完全模板化的版本相比能显著缩短编译时间并减小二进制代码体积。相关核心类型包括:
make_format_args(T&...):从参数构造类型擦除的参数包;basic_format_args/format_args:类型擦除后的参数集合;basic_format_arg:单个类型擦除的参数。
命名参数
通过fmt::arg(const char*, const T&)可以为参数命名,配合{name}引用。例如:
fmt::format("{greeting}, {name}!", fmt::arg("greeting", "hi"), fmt::arg("name", "fmt")); // 结果: "hi, fmt!"兼容性
fmt::basic_string_view/fmt::string_view提供了轻量的字符串视图,用于在无需std::string_view依赖的场合接收字符串参数,是fmt/base.h中const char*、fmt::string_viewformatter 所覆盖的类型之一。
完整格式化 API(fmt/format.h)
fmt/format.h定义完整的格式化 API,提供额外的格式化函数与 locale 支持:
format(format_string<T...>, T&&...):格式化并返回std::string;vformat(string_view, format_args):接收类型擦除参数包的格式化;operator""_a():在fmt::literals中定义的字面量,可将"name"_a = value形式的表达式用于命名参数构造。
工具函数
ptr(T):将对象指针格式化为其地址(fmt::format("{}", fmt::ptr(obj)));underlying(Enum):取枚举的底层值(format_as示例中的fmt::underlying(f));to_string(const T&):等价于fmt::format("{}", value);group_digits(T):对整数按千位分组,例如fmt::format("{}", fmt::group_digits(1234567));detail::buffer:格式化输出底层缓冲抽象;basic_memory_buffer:动态增长的栈上/堆上混合内存缓冲,是format_to系列函数的常用输出目标,也是自定义分配器与自定义格式化函数的基础。
系统错误
{fmt} 不使用errno向用户传递错误,但它可能会调用设置errno的系统函数。用户不应假设库函数会保留errno的值。相关接口:
system_error:构造携带格式化消息的std::system_error;format_system_error:将系统错误码对应的消息格式化到缓冲区。
自定义分配器
{fmt} 支持自定义动态内存分配器。自定义分配器类可以作为模板参数传给fmt::basic_memory_buffer:
using custom_memory_buffer = fmt::basic_memory_buffer<char, fmt::inline_buffer_size, custom_allocator>;也可以编写使用自定义分配器的格式化函数:
using custom_string = std::basic_string<char, std::char_traits<char>, custom_allocator>; auto vformat(custom_allocator alloc, fmt::string_view fmt, fmt::format_args args) -> custom_string { auto buf = custom_memory_buffer(alloc); fmt::vformat_to(std::back_inserter(buf), fmt, args); return custom_string(buf.data(), buf.size(), alloc); } template <typename ...Args> auto format(custom_allocator alloc, fmt::string_view fmt, const Args& ... args) -> custom_string { return vformat(alloc, fmt, fmt::make_format_args(args...)); }分配器仅用于输出容器。对内置类型与字符串类型,格式化函数通常不做任何堆分配,唯一的例外是非默认浮点格式化偶尔会回退到sprintf。
Locale 支持
默认情况下所有格式化都与 locale 无关(这保证了跨平台输出一致)。使用'L'格式规格可从 locale 插入对应的数字分隔符:
#include <fmt/format.h> #include <locale> std::locale::global(std::locale("en_US.UTF-8")); auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"fmt/format.h提供以下接受std::locale参数的重载(locale 类型被设计为模板参数,以避免昂贵的<locale>头文件包含):
format(locale_ref, format_string<T...>, T&&...)format_to(OutputIt, locale_ref, format_string<T...>, T&&...)formatted_size(locale_ref, format_string<T...>, T&&...)
Legacy 编译期检查
FMT_STRING为旧编译器开启编译期检查:要求 C++14 或更高版本,在 C++11 下为空操作。若要强制使用 legacy 编译期检查,可定义预处理变量FMT_ENFORCE_COMPILE_STRING——设置后,接受FMT_STRING的函数遇到普通字符串将编译失败。
Range 与 Tuple 格式化(fmt/ranges.h)
fmt/ranges.h为 range 与 tuple 提供格式化支持:
#include <fmt/ranges.h> fmt::print("{}", std::tuple<char, int>{'a', 42}); // 输出: ('a', 42)使用fmt::join可以用自定义分隔符连接 tuple/range 元素:
#include <fmt/ranges.h> auto t = std::tuple<int, char>{1, 'a'}; fmt::print("{}", fmt::join(t, ", ")); // 输出: 1, afmt::join的三种重载形式:
join(Range&&, string_view):连接整个 range;join(It, Sentinel, string_view):连接迭代器区间[It, Sentinel);join(std::initializer_list<T>, string_view):连接初始化列表。
标准容器(如std::vector)的格式化在 README 中也有演示:fmt::print("{}\n", v)对std::vector<int> v = {1, 2, 3}输出[1, 2, 3]。
日期与时间格式化(fmt/chrono.h)
fmt/chrono.h为以下类型提供 formatter:
std::chrono::durationstd::chrono::time_pointstd::tm
格式语法见《Format String Syntax》的 Chrono Format Specifications 一节。
示例:
#include <fmt/chrono.h> int main() { auto now = std::chrono::system_clock::now(); fmt::print("The date is {:%Y-%m-%d}.\n", now); // 输出: The date is 2020-11-07. // (2020-11-07 会被替换为当前日期) using namespace std::literals::chrono_literals; fmt::print("Default format: {} {}\n", 42s, 100ms); // 输出: Default format: 42s 100ms fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s); // 输出: strftime-like format: 03:15:30 }此外还提供gmtime(std::time_t)工具,将时间戳转换为 UTC 的std::tm。从源码 include/fmt/chrono.h 可以看到,duration 默认格式化为“数值 + 单位后缀”,time_point 默认输出YYYY-MM-DD HH:MM:SS.ffffff形式(见 README.md 的输出示例)。
标准库类型格式化(fmt/std.h)
fmt/std.h为以下标准库类型提供 formatter:
std::atomicstd::atomic_flagstd::bitsetstd::error_codestd::exceptionstd::filesystem::pathstd::monostatestd::optionalstd::source_locationstd::thread::idstd::variant
此外还提供智能指针格式化工具:
ptr(const std::unique_ptr<T, Deleter>&)ptr(const std::shared_ptr<T>&)
Variants
std::variant只有在每个备选类型都可格式化时才能格式化,且要求编译器支持__cpp_lib_variant特性测试宏:
#include <fmt/std.h> fmt::print("{}", std::variant<char, float>('x')); // 输出: variant('x') fmt::print("{}", std::variant<std::monostate, char>()); // 输出: variant(monostate)位域与打包结构体
格式化位域(bit-field)或带__attribute__((packed))的结构体字段时,需要通过强制转换或一元+将其转换为底层或兼容类型:
struct smol { int bit : 1; }; auto s = smol(); fmt::print("{}", +s.bit);这是 C++ "完美转发"机制的一个已知限制。
枚举格式化(fmt/enum.h)
fmt/enum.h支持对用fmt::as_identifiers注解的枚举进行格式化——这样的枚举会以匹配其枚举值的枚举器标识符(identifier)形式输出:
#include <fmt/enum.h> enum class [[=fmt::as_identifiers]] color { red, green, blue }; fmt::print("{}", color::green); // 输出: green这类枚举使用字符串格式规格格式化,例如:
fmt::print("[{:>7}]", color::red); // 输出: [ red]由于标识符只能以char字符串形式获得,注解枚举不能用其他字符类型格式化。多条规则:
- 若多个枚举器值相同,按声明顺序取第一个;
- 不匹配任何枚举器的值,先以十进制底层值表示,再套用字符串格式化:
fmt::print("{}", static_cast<color>(42)); // 输出: 42 - 未注解的枚举不受影响,按原有方式格式化(scoped enum 仍需
format_as或formatter特化,见上文“格式化用户自定义类型”)。
该特性使用两个 C++26 特性:reflection(反射)获取枚举器标识符,annotations(注解)通过fmt::as_identifiers选择启用,因此需要支持反射的编译器,GCC 下可能需要额外标志如-freflection。宏FMT_USE_REFLECTION在反射可用时为1,否则为0,用户也可以自行定义以禁用反射。从源码 include/fmt/enum.h 可以看到,检测逻辑是:用户显式定义优先,其次检查__cpp_impl_reflection && __cpp_lib_reflection。当以模块方式构建 {fmt} 时,反射支持在模块编译时检测,因此只有模块以反射启用方式构建,导入者才可用此 API。
编译期支持(fmt/compile.h)
fmt/compile.h提供格式字符串编译与编译期(constexpr)格式化,通过FMT_COMPILE宏或fmt::literals中定义的_cf用户自定义字面量启用。标记了FMT_COMPILE或_cf的格式字符串会在编译期被解析、检查并转换成高效的格式化代码。它支持内置类型、字符串类型,以及formatter特化中format方法以格式上下文类型为模板参数的用户自定义类型。例如:
struct point { double x; double y; }; template <> struct fmt::formatter<point> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template <typename FormatContext> auto format(const point& p, FormatContext& ctx) const { return format_to(ctx.out(), "({}, {})"_cf, p.x, p.y); } }; using namespace fmt::literals; std::string s = fmt::format("{}"_cf, point(4, 2));需要提醒:与默认 API 相比,格式字符串编译可能生成更多二进制代码,只建议在格式化是性能瓶颈的地方使用。
同一套 API 也支持在constexpr/consteval函数中进行编译期格式化。此外还有实验性的FMT_STATIC_FORMAT,可在编译期格式化为精确所需大小的字符串。编译期格式化要求内置 formatter 或用户自定义 formatter 的format方法为constexpr:
template <> struct fmt::formatter<point> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template <typename FormatContext> constexpr auto format(const point& p, FormatContext& ctx) const { return format_to(ctx.out(), "({}, {})"_cf, p.x, p.y); } }; constexpr auto s = FMT_STATIC_FORMAT("{}", point(4, 2)); const char* cstr = s.c_str(); // 指向静态字符串 "(4, 2)"从源码 include/fmt/compile.h 看,FMT_COMPILE在支持consteval时展开为FMT_STRING_IMPL(s, fmt::compiled_string),否则回退为FMT_STRING(s);FMT_STATIC_FORMAT内部先以编译后的字符串计算formatted_size,再在+1(终止符)大小的固定缓冲上完成格式化。
终端颜色与文本样式(fmt/color.h)
fmt/color.h提供终端颜色与文本样式输出支持:
print(text_style, format_string<T...>, T&&...):带样式的打印;fg(detail::color_type):前景色;bg(detail::color_type):背景色;styled(const T&, text_style):将样式应用于单个值。
样式可通过|组合。README 的示例展示了完整的用法:
#include <fmt/color.h> int main() { fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "Hello, {}!\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", "世界"); }fmt::color提供了大量具名颜色(如crimson、floral_white、steel_blue等),fmt::emphasis提供bold、italic、underline等样式。
系统 API(fmt/os.h)
fmt/os.h提供系统级 API:
ostream:基于 {fmt} 内部缓冲的轻量文件输出流类,见 include/fmt/os.h;output_file(cstring_view, T...):打开输出文件并返回ostream对象:#include <fmt/os.h> int main() { auto out = fmt::output_file("guide.txt"); out.print("Don't {}", "Panic"); }windows_error:构造携带格式化消息的std::system_error,面向 Windows 错误码(源码中对应vwindows_error/report_windows_error)。
这些 API 可以通过 CMake 选项FMT_OS=OFF整体禁用(见下文“配置选项”)。
std::ostream支持(fmt/ostream.h)
fmt/ostream.h提供std::ostream支持,包括格式化那些已重载插入运算符(operator<<)的用户自定义类型。要让某类型通过std::ostream可格式化,只需提供继承自ostream_formatter的formatter特化:
#include <fmt/ostream.h> struct date { int year, month, day; friend std::ostream& operator<<(std::ostream& os, const date& d) { return os << d.year << '-' << d.month << '-' << d.day; } }; template <> struct fmt::formatter<date> : ostream_formatter {}; std::string s = fmt::format("The date is {}", date{2012, 12, 9}); // s == "The date is 2012-12-9"此外还有:
streamed(const T&):将任意类型以流式方式格式化(调用其operator<<);print(std::ostream&, format_string<T...>, T&&...):格式化并输出到任意std::ostream。
动态参数列表(fmt/args.h)
头文件fmt/args.h提供dynamic_format_arg_store,一种 builder 风格的 API,用于动态地构造格式参数列表(典型场景:运行期决定参数个数,如日志系统)。从源码 include/fmt/args.h 可以看到其基本用法:
fmt::dynamic_format_arg_store<fmt::format_context> store; store.push_back(42); store.push_back("abc"); store.push_back(1.5f); // 之后 store 可传给 vformat 系列函数使用push_back有三种重载:
push_back(const T&):按值存入参数(生命周期由 store 管理);push_back(std::reference_wrapper<T>):以引用方式存入,避免拷贝;push_back(const named_arg<T, char_type>&):存入命名参数(与fmt::arg生成的命名参数兼容)。
安全的 printf(fmt/printf.h)
fmt/printf.h提供 printf 风格的格式化功能,使用 printf 格式字符串语法并支持 POSIX 位置参数扩展。与标准对应物不同,fmt版本是类型安全的——如果参数类型与格式规格不匹配会抛出异常:
printf(string_view, const T&...):输出到 stdout;fprintf(std::FILE*, string_view, const T&...):输出到指定FILE*;sprintf(string_view, const T&...):返回std::string。
宽字符串(fmt/xchar.h)
可选的fmt/xchar.h提供wchar_t及“异国”字符类型支持:
wstring_view:宽字符字符串视图;wformat_context:宽字符格式化上下文;to_wstring(const T&):等价于fmt::format(L"{}", value),返回std::wstring。
与 C++20std::format的兼容性
{fmt} 实现了 C++20 格式化库的绝大部分功能,差异如下:
- 名称定义在
fmt命名空间而非std,避免与标准库实现冲突; - 宽度计算不使用 grapheme 聚类(该功能曾在独立分支实现,尚未合并);
- {fmt} 的默认浮点表示使用能提供 round-trip 保证的最小精度(与 Java、Python 等语言类似);
std::format目前按std::to_chars的语义规定——后者倾向于生成最少字符数(忽略冗余数字与指数符号),有时会产生比必要更多的十进制位。
配置选项
{fmt} 通过 CMake 选项与预处理器宏提供配置能力,可启用/禁用特性并针对二进制体积优化。例如配置 CMake 时用-DFMT_OS=OFF可禁用fmt/os.h中定义的 OS 专属 API。
CMake 选项
FMT_OS:设为OFF时禁用 OS 专属 API(fmt/os.h)。默认ON(见 CMakeLists.txt 中option(FMT_OS "Include OS-specific APIs." ON));FMT_UNICODE:设为OFF时在 Windows/MSVC 上禁用 Unicode 支持;其他平台 Unicode 始终启用。默认ON。
宏
FMT_HEADER_ONLY:定义后启用 header-only 模式,是fmt::fmt-header-onlyCMake target 的替代方案。默认不定义。(CMakeLists.txt 中fmt-header-onlytarget 通过FMT_HEADER_ONLY=1编译定义实现。)FMT_USE_EXCEPTIONS:设为0时禁用异常的使用。默认1(以-fno-exceptions编译时为0)。源码 include/fmt/base.h 中的检测逻辑:用户显式定义优先,否则依次检查 GCC 的__EXCEPTIONS、Clang 的__cpp_exceptions、MSVC 的_HAS_EXCEPTIONS自动判定。FMT_USE_LOCALE:设为0时禁用 locale 支持。默认1(FMT_OPTIMIZE_SIZE > 1时为0)。源码中定义为FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1)(见 include/fmt/base.h)。FMT_CUSTOM_ASSERT_FAIL:设为1时允许用户提供自定义的fmt::assert_fail函数,它在断言失败时被调用;若异常被禁用,也在运行时错误时被调用。默认0。(fmt::assert_fail的声明见 include/fmt/base.h。)FMT_BUILTIN_TYPES:设为0时禁用除int之外的算术与字符串类型的内置处理,以减小库体积,代价是每次调用增加额外开销。默认1。FMT_OPTIMIZE_SIZE:控制二进制体积优化:0:关闭(默认);1:应用部分优化;2:默认禁用 locale 支持、部分 Unicode 特性与命名参数,并应用更激进的优化。
二进制体积优化
为了在尽可能减小 {fmt} 二进制体积(代价是损失部分特性)时可使用如下配置:
- CMake 选项:
FMT_OS=OFF
- 宏:
FMT_BUILTIN_TYPES=0FMT_OPTIMIZE_SIZE=2
延伸阅读
- 《Format String Syntax》:完整的格式字符串语法,包括替换字段文法、fill/align/sign/width/precision/type 等格式规格的逐项说明;
- 《Getting Started》:编译与接入方式(CMake、header-only、模块);
- 入门示例:打印、格式化、日期时间、容器、文件输出、彩色输出的完整代码;
- 测试目录 test/ 下的
base-test.cc、format-test.cc、chrono-test.cc、ranges-test.cc、std-test.cc、enum-test.cc、compile-test.cc、xchar-test.cc、printf-test.cc、args-test.cc、os-test.cc等文件可作为各 API 行为的可执行验证。
【免费下载链接】fmtA modern formatting library项目地址: https://gitcode.com/GitHub_Trending/fm/fmt
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考