std::range_formatter
定义在头文件 <format> 中 |
||
template< class T, class CharT = char > requires std::same_as<std::remove_cvref_t<T>, T> && std::formattable<T, CharT> |
(自 C++23 起) | |
std::range_formatter
是一个辅助类模板,用于实现 std::formatter 针对范围类型的特化。
内容 |
[编辑] 范围格式规范
range-format-spec 的语法为
range-fill-and-align (可选) width (可选) n (可选) range-type (可选) range-underlying-spec (可选) |
|||||||||
range-fill-and-align 的解释方式与 fill-and-align 相同,只是 range-fill-and-align 中的 fill 为除 {
、}
或 :
之外的任何字符。
width 在 标准格式宽度规范 中描述。
n
选项会导致范围在没有开始和结束括号的情况下进行格式化。
assert(std::format("{}", views::iota(1, 5)) == "[1, 2, 3, 4]"); assert(std::format("{:n}", views::iota(1, 5)) == "1, 2, 3, 4");
range-underlying-spec 中的 format-spec (其语法等效于 :
format-spec),如果存在,将由范围元素格式化程序 std::formatter<T, CharT>
解释。
std::array ints{12, 10, 15, 14}; assert(std::format("{}", ints) == "[12, 10, 15, 14]"); assert(std::format("{::X}", ints) == "[C, A, F, E]"); assert(std::format("{:n:_^4}", ints) == "_12_, _10_, _15_, _14_");
range-type 会改变范围的格式化方式,某些选项只对某些参数类型有效。
可用的范围表示类型为
-
m
:表示开始括号应为 "{",结束括号应为 "}",分隔符应为 ", ",并且每个范围元素应像在 tuple-type 中指定了m
一样进行格式化 (在 tuple-format-spec 中)。
- 如果选择
m
作为 range-type,则除非T
是以下类型的特化,否则程序将格式错误:
- std::pair,或者
- std::tuple,使得 std::tuple_size_v<T> == 2 为 true。
- 如果选择
std::array char_pairs { std::pair{'A', 5}, std::pair{'B', 10}, std::pair{'C', 12} }; assert(std::format("{}", char_pairs) == "[('A', 5), ('B', 10), ('C', 12)]"); assert(std::format("{:m}", char_pairs) == "{'A': 5, 'B': 10, 'C': 12}");
-
s
:表示范围应作为字符串进行格式化。 -
?s
:表示范围应作为 转义字符串 进行格式化。
- 如果选择
s
或?s
作为 range-type,则不应该在格式说明符中包含n
选项和 range-underlying-spec,并且 - 除非
T
为CharT
,否则程序将格式错误。
- 如果选择
std::array star{'S', 'T', 'A', 'R'}; assert(std::format("{}", star) == "['S', 'T', 'A', 'R']"); assert(std::format("{:s}", star) == "STAR"); assert(std::format("{:?s}", star) == "\"STAR\"");
[编辑] 成员对象
成员名称 | 定义 |
underlying_ (私有) |
类型为 std::formatter<T, CharT> 的基础格式化程序 (仅用于说明的成员对象*) |
separator_ (私有) |
表示范围格式化结果的分隔符的字符串。默认分隔符为 ", "。 (仅用于说明的成员对象*) |
opening-bracket_ (私有) |
表示范围格式化结果的开始括号的字符串。默认开始括号为 "["。 (仅用于说明的成员对象*) |
closing-bracket_ (私有) |
表示范围格式化结果的结束括号的字符串。默认结束括号为 "]"。 (仅用于说明的成员对象*) |
[编辑] 成员函数
set_separator |
为范围格式化结果设置指定的分隔符 (公有成员函数) |
set_brackets |
为范围格式化结果设置指定的开括号和闭括号。 (公有成员函数) |
底层 |
返回底层格式化器。 (公有成员函数) |
解析 |
根据 范围格式规范 解析格式说明符。 (公有成员函数) |
format |
根据 范围格式规范 写入范围格式化输出。 (公有成员函数) |
std::range_formatter::set_separator
constexpr void set_separator( std::basic_string_view<CharT> sep ) noexcept; |
||
将 sep 赋值给 separator_
。
std::range_formatter::set_brackets
constexpr void set_brackets( std::basic_string_view<CharT> opening, std::basic_string_view<CharT> closing ) noexcept; |
||
分别将 opening 和 closing 赋值给 opening-bracket_
和 closing-bracket_
。
std::range_formatter::underlying
constexpr std::formatter<T, CharT>& underlying(); |
(1) | |
constexpr const std::formatter<T, CharT>& underlying() const; |
(2) | |
返回 underlying_
(底层格式化器)。
std::range_formatter::parse
template< class ParseContext > constexpr auto parse( ParseContext& ctx ) -> ParseContext::iterator; |
||
将格式说明符解析为 范围格式规范,并将解析后的说明符存储在当前对象中。
调用 underlying_
.parse(ctx) 解析 格式规范 在 范围格式规范 中,或者如果没有后者,则解析为空的 格式规范。
如果存在 范围类型 或 n
选项,则根据需要修改 opening-bracket_
、closing-bracket_
和 separator_
的值。
如果满足以下条件,则调用 underlying_
.set_debug_format():
- 范围类型 既不是
s
也不是?s
, -
underlying_
.set_debug_format() 是一个有效的表达式,以及 - 不存在 范围底层规范。
返回指向 范围格式规范 末尾的迭代器。
std::range_formatter::format
template< ranges::input_range R, class FormatContext > requires std::formattable<ranges::range_reference_t<R>, CharT> && |
||
如果 范围类型 是 s
或 ?s
,则将格式化的 std::basic_string<CharT>(std::from_range, r) 作为字符串或转义字符串分别写入 ctx.out() 中。
否则,根据 范围格式规范,按顺序将以下内容写入 ctx.out() 中:
-
opening-bracket_
, - 对于范围 r 中的每个可格式化元素 e
- 通过
underlying_
写入 e 的结果,以及 -
separator_
,除非 e 是 r 中的最后一个元素,以及
- 通过
-
closing-bracket_
.
返回指向输出范围末尾的迭代器。
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于之前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
LWG 3892 | C++23 | 嵌套范围的格式化不正确 | 已更正 |
[编辑] 另请参阅
(C++20) |
为给定类型定义格式化规则 (类模板) |