std::formatter
定义于头文件 <format>
|
||
template<class T, class CharT = char> struct formatter; |
(C++20 起) | |
formatter
的被启用特化对给定类型定义格式化规则。被启用特化必须满足格式化器 (Formatter) 要求。特别是,它们定义成员函数或函数模板 parse
与 format
,使得:
- 成员
parse
……
- 接受单个 std::basic_format_parse_context<CharT> 类型参数
pc
- 分析范围
[pc.begin(), pc.end())
中的类型T
的格式说明 - 存储分析出的格式声明符于
*this
- 返回表示格式说明结尾的 std::basic_format_parse_context<CharT>::iterator 类型值
- 可能抛出 std::format_error 以指示格式字符串中的错误
- 接受单个 std::basic_format_parse_context<CharT> 类型参数
- 成员
format
……
- 接受二个参数:
T
类型参数t
,后随 std::basic_format_context<OutputIt, CharT> 类型参数fc
,其中OutputIt
是输出迭代器类型 - 按照
*this
中存储的说明符格式化t
- 写输出到
fc.out()
- 返回表示输出结尾的 std::basic_format_context<OutputIt, CharT>::iterator 类型值
- 输出必须仅依赖
t
、fc.locale()
及最后分析的格式说明符
- 接受二个参数:
被启用特化为可默认构造 (DefaultConstructible) 、可复制构造 (CopyConstructible) 、可复制赋值 (CopyAssignable) 、可交换 (Swappable) 且可析构 (Destructible) 。
对每个未被库或用户提供被启用特化 std::formatter<T, CharT>
的类型 T
与 CharT
,该特化是完整类型且被禁用。被禁用特化不满足格式化器 (Formatter) 要求,且 std::is_default_constructible_v 、 std::is_copy_constructible_v 、 std::is_move_constructible_v 、 std::is_copy_assignable_v 、 std::is_move_assignable_v 皆为 false 。
对基本类型和字符串类型的标准特化
以下列表中, CharT
为 char
或 wchar_t
, ArithmeticT
是任何 cv 无限定的算术类型,除了 char
、 wchar_t
、 char8_t
、 char16_t
或 char32_t
。
template<> struct formatter<char, char>; template<> struct formatter<char, wchar_t>; |
||
对其他指针和指向成员指针的格式化器被禁用。
如 std::formatter<wchar_t, char>
和 std::formatter<const char*, wchar_t>
这些会要求编码转换的特化被禁用。
标准格式说明
对于基本类型和字符串类型,格式说明基于 Python 中的格式说明。
格式说明的语法是:
填充与对齐(可选) 符号(可选) # (可选) 0 (可选) 宽度(可选) 精度(可选) L (可选) 类型(可选)
|
|||||||||
符号 、 #
及 0
选项仅当使用整数或浮点显示类型时合法。
填充与对齐
填充与对齐 是一个可选的填充字符(可为任何 {
或 }
外的的字符),后随对齐选项 <
、 >
、 ^
之一。对齐选项的意义如下:
-
<
:强制域对齐到可用空间起始。这在使用非整数非浮点显示类型时为默认。 -
>
:强制域对齐到可用空间末尾。这在使用整数或浮点显示类型时为默认。 -
^
:强制域在可用空间中央,通过在值的前面插入 ⌊
⌋ 个字符,后面插入 ⌈n 2
⌉ 个字符,其中 n 是待插入的总字符数。n 2
char c = 120; auto s0 = std::format("{:6}", 42); // s0 的值为 " 42" auto s1 = std::format("{:6}", 'x'); // s1 的值为 "x " auto s2 = std::format("{:*<6}", 'x'); // s2 的值为 "x*****" auto s3 = std::format("{:*>6}", 'x'); // s3 的值为 "*****x" auto s4 = std::format("{:*^6}", 'x'); // s4 的值为 "**x***" auto s5 = std::format("{:6d}", c); // s5 的值为 " 120" auto s6 = std::format("{:6}", true); // s6 的值为 "true "
符号、 # 与 0
符号 选项能为下列之一:
-
+
:指示符号应该一同用于非负数和负数。在非负数的输出值前插入+
号。 -
-
:指示符号应该仅用于负数(这是默认行为)。 - 空格:指示应对非负数使用前导空格,而对负数使用负号。
负零被当作负数。
符号 选项应用于浮点无穷大和 NaN 。
double inf = std::numeric_limits<double>::infinity(); double nan = std::numeric_limits<double>::quiet_NaN(); auto s0 = std::format("{0:},{0:+},{0:-},{0: }", 1); // s0 的值为 "1,+1,1, 1" auto s1 = std::format("{0:},{0:+},{0:-},{0: }", -1); // s1 的值为 "-1,-1,-1,-1" auto s2 = std::format("{0:},{0:+},{0:-},{0: }", inf); // s2 的值为 "inf,+inf,inf, inf" auto s3 = std::format("{0:},{0:+},{0:-},{0: }", nan); // s3 的值为 "nan,+nan,nan, nan"
#
选项导致将替用形式用于转换。
- 对于整数类型,使用二进制、八进制或十六进制显示类型时,替用形式插入前缀(
0b
、0
或0x
)到输出值中,若有符号则于符号(可为空格)前,否则于输出值前。 - 对于浮点类型,替用形式导致有限值的转换结果始终含有小数点字符,即使其后无数位。正常情况下,小数点字符仅若有数位后随它才出现于转换结果。另外,对于
g
与G
转换,不从结果移除尾随的零。
0
选项以前导零填充域(后随任何符号或底)到域宽,除了应用到无穷大或 NaN 时。若 0
字符与对齐选项一同出现,则忽略 0
字符。
char c = 120; auto s1 = std::format("{:+06d}", c); // s1 的值为 "+00120" auto s2 = std::format("{:#06x}", 0xa); // s2 的值为 "0x000a" auto s3 = std::format("{:<06}", -42); // s3 的值为 "-42 " (因 < 对齐忽略 0 )
宽度与精度
宽度 为正十进制数,或嵌套的替换域( {}
或 {
n}
)。宽度若存在则指定最小域宽。
精度 为点( .
)后随非负十进制数或嵌套的替换域。此域指示精度或最大域大小。它仅能用于浮点与字符串类型。对于浮点类型,此域指定格式化精度。对于字符串类型,它指定将从字符串使用多少字符。
若 宽度 或 精度 中使用嵌套的替换域,而对应的参数不是整数类型,或为负,或对于 宽度 为零,则抛出 std::format_error 类型异常。
本节未完成 原因:小示例 |
L (本地环境特定的格式化)
L
选项导致使用本地环境特定的形式。此选项仅对算术类型合法。
- 对于整数类型,本地环境特定形式按照环境的本地环境,插入适合的数位组分隔字符。
- 对于浮点类型,本地环境特定形式按照环境的本地环境,插入适合的数位组和底分隔字符。
- 对于
bool
的文本表示,本地环境特定形式使用如同通过 std::numpunct::truename 或 std::numpunct::falsename 获得的字符串。
类型
类型 选项确定应该如何显示数据。
可用的字符串显示类型为:
- 无、
s
:复制字符串到输出。
可用的 char
、 wchar_t
与 bool
外的整数类型的整数显示类型为:
-
b
:二进制格式。如同通过调用 std::to_chars(first, last, value, 2) 产生输出。底前缀为0b
。 -
B
:同b
,除了底前缀为0B
。 -
c
:复制字符 static_cast<CharT>(value) 到输出,其中 CharT 是格式字符串的字符类型。若值不在 CharT 的可表示值的范围中则抛出 std::format_error 。 -
d
:十进制格式。如同通过调用 std::to_chars(first, last, value) 产生输出。 -
o
:八进制格式。如同通过调用 std::to_chars(first, last, value, 8).产生输出。若对应参数值非零则底前缀为0
,否则为空。 -
x
:十六进制格式。如同通过调用 std::to_chars(first, last, value, 16) 产生输出。底前缀为0x
。 -
X
:同x
,除了对 9 以上的数字使用大写字母且底前缀为0X
。 - 无:同
d
。
可用的 char
及 wchar_t
表示类型为:
- 无、
c
:复制字符到输出。 -
b
、B
、d
、o
、x
、X
:使用整数表示类型。
可用的 bool
表示类型为:
- 无、
s
:复制文本表示(true
或false
或本地环境特定形式)到输出。 -
b
、B
、c
、d
、o
、x
、X
:以值static_cast<unsigned char>(value)
使用整数表示类型。
可用的浮点表示类型为:
-
a
:若指定精度,则如同通过调用 std::to_chars(first, last, value, std::chars_format::hex, precision) 产生输出,其中precision
是指定的精度,否则如同通过 std::to_chars(first, last, value, std::chars_format::hex) 产生输出。 -
A
:同a
,除了对 9 以上的数字使用大写字母并用P
指示指数。 -
e
:如同通过调用 std::to_chars(first, last, value, std::chars_format::scientific, precision) 产生输出,其中precision
为指定的精度,或若未指定精度则为 6 。 -
E
:同e
,除了用E
指示指数。 -
f
、F
:如同通过调用 std::to_chars(first, last, value, std::chars_format::fixed, precision) 产生输出,其中precision
为指定的精度,或若未指定精度则为 6 。 -
g
:如同通过调用 std::to_chars(first, last, value, std::chars_format::general, precision) 产生输出,其中precision
为指定的精度,或若未指定精度则为 6 。 -
G
:同g
,除了用E
指示指数。 - 无:若指定精度,则如同通过调用 std::to_chars(first, last, value, std::chars_format::general, precision) 产生输出,其中
precision
为指定的精度;否则如同通过调用 std::to_chars(first, last, value) 产生输出。
对于小写表示类型,分别格式化无穷大和 NaN 为 inf
与 nan
。对于大写表示类型,分别格式化无穷大和 NaN 为 INF
与 NAN
。
可用的指针表示类型(亦用于 std::nullptr_t
)为:
- 无、
p
:若定义 std::uintptr_t ,则如同通过调用 std::to_chars(first, last, reinterpret_cast<std::uintptr_t>(value), 16) 产生输出,并添加前缀0x
到输出;否则输出为实现定义。
库类型的标准特化
std::formatter 的特化,按提供的格式格式化 duration (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 sys_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 utc_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 tai_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 gps_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 file_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 local_time (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 day (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 month (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 weekday (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 weekday_indexed (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 weekday_last (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 month_day (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 month_day_last (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 month_weekday (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 month_weekday_last (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year_month (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year_month_day (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year_month_day_last (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year_month_weekday (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 year_month_weekday_last (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 hh_mm_ss (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 sys_info (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 local_info (类模板特化) | |
std::formatter 的特化,按照提供的格式格式化 zoned_time (类模板特化) |
示例
#include <format> #include <iostream> // 类型 T 的包装 template<class T> struct Box { T value; }; // 能用被包装值的格式说明格式化包装 Box<T> template<class T, class CharT> struct std::formatter<Box<T>, CharT> : std::formatter<T, CharT> { // 从基类继承 parse() // 通过以被包装值调用基类实现定义 format() template<class FormatContext> auto format(Box<T> t, FormatContext& fc) { return std::formatter<T, CharT>::format(t.value, fc); } }; int main() { Box<int> v = { 42 }; std::cout << std::format("{:#x}", v); }
输出:
0x2a