std::formatter

来自cppreference.com
< cpp‎ | utility‎ | format
 
 
工具库
通用工具
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)

初等字符串转换
(C++17)
(C++17)
栈踪
 
格式化库
格式化函数
(C++20)
(C++20)
(C++20)
(C++20)
格式化器
formatter
(C++20)
格式化参数
格式错误
 
定义于头文件 <format>
template<class T, class CharT = char>
struct formatter;
(C++20 起)

formatter 的被启用特化对给定类型定义格式化规则。被启用特化必须满足格式化器 (Formatter) 要求。尤其是它们定义可调用实体 parseformat

对每组未对其启用特化 std::formatter<T, CharT> 的类型 TCharT ,该特化是完整类型且被禁用。

被禁用特化不满足格式化器 (Formatter) 要求,且下列值均为 false

对基本类型和字符串类型的标准特化

以下列表中, CharTcharwchar_tArithmeticT 是任何 cv 无限定的算术类型,除了 charwchar_tchar8_tchar16_tchar32_t

template<> struct formatter<char, char>;

template<> struct formatter<char, wchar_t>;
template<> struct formatter<wchar_t, wchar_t>;

template<> struct formatter<CharT*, CharT>;
template<> struct formatter<const CharT*, CharT>;
template<std::size_t N> struct formatter<const CharT[N], CharT>;
template<class Traits, class Alloc>
  struct formatter<std::basic_string<CharT, Traits, Alloc>, CharT>;
template<class Traits>
  struct formatter<std::basic_string_view<CharT, Traits>, CharT>;

template<> struct formatter<ArithmeticT, CharT>;

template<> struct formatter<std::nullptr_t, CharT>;
template<> struct formatter<void*, CharT>;

template<> struct formatter<const void*, CharT>;

对其他指针和指向成员指针的格式化器被禁用。

std::formatter<wchar_t, char>std::formatter<const char*, wchar_t> 这些会要求编码转换的特化被禁用。

标准格式说明

对于基本类型和字符串类型,格式说明基于 Python 中的格式说明

格式说明的语法是:

填充与对齐(可选) 符号(可选) #(可选) 0(可选) 宽度(可选) 精度(可选) L(可选) 类型(可选)

符号#0 选项仅当使用整数或浮点显示类型时合法。

填充与对齐

填充与对齐 是一个可选的填充字符(可为任何 {} 外的的字符),后随对齐选项 <>^ 之一。对齐选项的意义如下:

  • < :强制域对齐到可用空间起始。这在使用非整数非浮点显示类型时为默认。
  • > :强制域对齐到可用空间末尾。这在使用整数或浮点显示类型时为默认。
  • ^ :强制域在可用空间中央,通过在值的前面插入
    n
    2
    个字符,后面插入
    n
    2
    个字符,其中 n 是待插入的总字符数。
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"

# 选项导致将替用形式用于转换。

  • 对于整数类型,使用二进制、八进制或十六进制显示类型时,替用形式插入前缀( 0b00x )到输出值中,若有符号则于符号(可为空格)前,否则于输出值前。
  • 对于浮点类型,替用形式导致有限值的转换结果始终含有小数点字符,即使其后无数位。正常情况下,小数点字符仅若有数位后随它才出现于转换结果。另外,对于 gG 转换,不从结果移除尾随的零。

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} )。宽度若存在则指定最小域宽。

精度 为点( . )后随非负十进制数或嵌套的替换域。此域指示精度或最大域大小。它仅能用于浮点与字符串类型。对于浮点类型,此域指定格式化精度。对于字符串类型,它提供要复制到输出的字符串前缀的估计宽度(见后述)的上界。对于以 Unicode 编码的字符串,复制到输出的文本是整个扩展字素集群的,使得估计宽度不大于精度的最长前缀。

宽度精度 中使用嵌套的替换域,而对应的参数不是整数类型,或为负,或对于 宽度 为零,则抛出 std::format_error 类型异常。

float pi = 3.14f;
auto s1 = std::format("{:10f}", pi);           // s1 = "  3.140000" (宽度 = 10 )
auto s2 = std::format("{:{}f}", pi, 10);       // s2 = "  3.140000" (宽度 = 10 )
auto s3 = std::format("{:.5f}", pi);           // s3 = "3.14000" (精度 = 5 )
auto s4 = std::format("{:.{}f}", pi, 5);       // s4 = "3.14000" (精度 = 5 )
auto s5 = std::format("{:10.5f}", pi);         // s5 = "   3.14000"
                                               // (宽度 = 10 ,精度 = 5 )
auto s6 = std::format("{:{}.{}f}", pi, 10, 5); // s6 = "   3.14000"
                                               // (宽度 = 10 ,精度 = 5 )
 
auto b1 = std::format("{:{}f}", pi, 10.0);     // 抛出:宽度不是整数类型
auto b2 = std::format("{:{}f}", pi, -10);      // 抛出:宽度为负
auto b3 = std::format("{:.{}f}", pi, 5.0);     // 抛出:精度不是整数类型

对于字符串类型,宽度定义为适合将它显示到终端的估计列位置数值。

就宽度计算目的,假设字符串用实现定义的编码。宽度计算的方法是未指定的,但对于以 Unicode 的字符串,实现应该估计字符串的宽度为其扩展字素集群中首个码位的估计宽度之和。若 Unicode 码位在下列范围内,则估计宽度为 2 ,否则为 1 :

  • U+1100 - U+115F
  • U+2329 - U+232A
  • U+2E80 - U+303E
  • U+3040 - U+A4CF
  • U+AC00 - U+D7A3
  • U+F900 - U+FAFF
  • U+FE10 - U+FE19
  • U+FE30 - U+FE6F
  • U+FF00 - U+FF60
  • U+FFE0 - U+FFE6
  • U+1F300 - U+1F64F
  • U+1F900 - U+1F9FF
  • U+20000 - U+2FFFD
  • U+30000 - U+3FFFD
auto s1 = std::format("{:.^5s}",   "🐱");      // s1 = ".🐱.."
auto s2 = std::format("{:.5s}",    "🐱🐱🐱");  // s2 = "🐱🐱"
auto s3 = std::format("{:.<5.5s}", "🐱🐱🐱");  // s3 = "🐱🐱."
L (本地环境特定的格式化)

L 选项导致使用本地环境特定的形式。此选项仅对算术类型合法。

  • 对于整数类型,本地环境特定形式按照环境的本地环境,插入适合的数位组分隔字符。
  • 对于浮点类型,本地环境特定形式按照环境的本地环境,插入适合的数位组和底分隔字符。
  • 对于 bool 的文本表示,本地环境特定形式使用如同通过 std::numpunct::truenamestd::numpunct::falsename 获得的字符串。
类型

类型 选项确定应该如何显示数据。

可用的字符串显示类型为:

  • 无、 s :复制字符串到输出。

可用的 charwchar_tbool 外的整数类型的整数显示类型为:

  • 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

可用的 charwchar_t 表示类型为:

  • 无、 c :复制字符到输出。
  • bBdoxX :使用整数表示类型。

可用的 bool 表示类型为:

  • 无、 s :复制文本表示( truefalse 或本地环境特定形式)到输出。
  • bBcdoxX :以值 static_cast<unsigned char>(value) 使用整数表示类型。

可用的浮点表示类型为:

对于小写表示类型,分别格式化无穷大和 NaN 为 infnan 。对于大写表示类型,分别格式化无穷大和 NaN 为 INFNAN

可用的指针表示类型(亦用于 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

参阅

格式化状态,包括所有格式化参数和输出迭代器
(类模板)