From Jason Turner

[format.formatter]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmph6qojmgy/{from.md → to.md} +339 -0
tmp/tmph6qojmgy/{from.md → to.md} RENAMED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Formatter <a id="format.formatter">[[format.formatter]]</a>
2
+
3
+ #### Formatter requirements <a id="formatter.requirements">[[formatter.requirements]]</a>
4
+
5
+ A type `F` meets the requirements if:
6
+
7
+ - it meets the
8
+ - *Cpp17DefaultConstructible* ([[cpp17.defaultconstructible]]),
9
+ - *Cpp17CopyConstructible* ([[cpp17.copyconstructible]]),
10
+ - *Cpp17CopyAssignable* ([[cpp17.copyassignable]]), and
11
+ - *Cpp17Destructible* ([[cpp17.destructible]])
12
+
13
+ requirements,
14
+ - it is swappable [[swappable.requirements]] for lvalues, and
15
+ - the expressions shown in [[formatter]] are valid and have the
16
+ indicated semantics.
17
+
18
+ Given character type `charT`, output iterator type `Out`, and formatting
19
+ argument type `T`, in [[formatter]]:
20
+
21
+ - `f` is a value of type `F`,
22
+ - `u` is an lvalue of type `T`,
23
+ - `t` is a value of a type convertible to (possibly const) `T`,
24
+ - `PC` is `basic_format_parse_context<charT>`,
25
+ - `FC` is `basic_format_context<Out, charT>`,
26
+ - `pc` is an lvalue of type `PC`, and
27
+ - `fc` is an lvalue of type `FC`.
28
+
29
+ `pc.begin()` points to the beginning of the *format-spec*
30
+ [[format.string]] of the replacement field being formatted in the format
31
+ string. If *format-spec* is empty then either `pc.begin() == pc.end()`
32
+ or `*pc.begin() == '}'`.
33
+
34
+ [*Note 1*: This allows formatters to emit meaningful error
35
+ messages. — *end note*]
36
+
37
+ #### Formatter specializations <a id="format.formatter.spec">[[format.formatter.spec]]</a>
38
+
39
+ The functions defined in [[format.functions]] use specializations of the
40
+ class template `formatter` to format individual arguments.
41
+
42
+ Let `charT` be either `char` or `wchar_t`. Each specialization of
43
+ `formatter` is either enabled or disabled, as described below.
44
+
45
+ [*Note 1*: Enabled specializations meet the requirements, and disabled
46
+ specializations do not. — *end note*]
47
+
48
+ Each header that declares the template `formatter` provides the
49
+ following enabled specializations:
50
+
51
+ - The specializations
52
+ ``` cpp
53
+ template<> struct formatter<char, char>;
54
+ template<> struct formatter<char, wchar_t>;
55
+ template<> struct formatter<wchar_t, wchar_t>;
56
+ ```
57
+ - For each `charT`, the string type specializations
58
+ ``` cpp
59
+ template<> struct formatter<charT*, charT>;
60
+ template<> struct formatter<const charT*, charT>;
61
+ template<size_t N> struct formatter<const charT[N], charT>;
62
+ template<class traits, class Allocator>
63
+ struct formatter<basic_string<charT, traits, Allocator>, charT>;
64
+ template<class traits>
65
+ struct formatter<basic_string_view<charT, traits>, charT>;
66
+ ```
67
+ - For each `charT`, for each cv-unqualified arithmetic type
68
+ `ArithmeticT` other than `char`, `wchar_t`, `char8_t`, `char16_t`, or
69
+ `char32_t`, a specialization
70
+ ``` cpp
71
+ template<> struct formatter<ArithmeticT, charT>;
72
+ ```
73
+ - For each `charT`, the pointer type specializations
74
+ ``` cpp
75
+ template<> struct formatter<nullptr_t, charT>;
76
+ template<> struct formatter<void*, charT>;
77
+ template<> struct formatter<const void*, charT>;
78
+ ```
79
+
80
+ The `parse` member functions of these formatters interpret the format
81
+ specification as a *std-format-spec* as described in
82
+ [[format.string.std]].
83
+
84
+ [*Note 2*: Specializations such as `formatter<wchar_t, char>` and
85
+ `formatter<const char*, wchar_t>` that would require implicit multibyte
86
+ / wide string or character conversion are disabled. — *end note*]
87
+
88
+ For any types `T` and `charT` for which neither the library nor the user
89
+ provides an explicit or partial specialization of the class template
90
+ `formatter`, `formatter<T, charT>` is disabled.
91
+
92
+ If the library provides an explicit or partial specialization of
93
+ `formatter<T, charT>`, that specialization is enabled except as noted
94
+ otherwise.
95
+
96
+ If `F` is a disabled specialization of `formatter`, these values are
97
+ `false`:
98
+
99
+ - `is_default_constructible_v<F>`,
100
+ - `is_copy_constructible_v<F>`,
101
+ - `is_move_constructible_v<F>`,
102
+ - `is_copy_assignable_v<F>`, and
103
+ - `is_move_assignable_v<F>`.
104
+
105
+ An enabled specialization `formatter<T, charT>` meets the requirements
106
+ [[formatter.requirements]].
107
+
108
+ [*Example 1*:
109
+
110
+ ``` cpp
111
+ #include <format>
112
+
113
+ enum color { red, green, blue };
114
+ const char* color_names[] = { "red", "green", "blue" };
115
+
116
+ template<> struct std::formatter<color> : std::formatter<const char*> {
117
+ auto format(color c, format_context& ctx) {
118
+ return formatter<const char*>::format(color_names[c], ctx);
119
+ }
120
+ };
121
+
122
+ struct err {};
123
+
124
+ std::string s0 = std::format("{}", 42); // OK, library-provided formatter
125
+ std::string s1 = std::format("{}", L"foo"); // error: disabled formatter
126
+ std::string s2 = std::format("{}", red); // OK, user-provided formatter
127
+ std::string s3 = std::format("{}", err{}); // error: disabled formatter
128
+ ```
129
+
130
+ — *end example*]
131
+
132
+ #### Class template `basic_format_parse_context` <a id="format.parse.ctx">[[format.parse.ctx]]</a>
133
+
134
+ ``` cpp
135
+ namespace std {
136
+ template<class charT>
137
+ class basic_format_parse_context {
138
+ public:
139
+ using char_type = charT;
140
+ using const_iterator = typename basic_string_view<charT>::const_iterator;
141
+ using iterator = const_iterator;
142
+
143
+ private:
144
+ iterator begin_; // exposition only
145
+ iterator end_; // exposition only
146
+ enum indexing { unknown, manual, automatic }; // exposition only
147
+ indexing indexing_; // exposition only
148
+ size_t next_arg_id_; // exposition only
149
+ size_t num_args_; // exposition only
150
+
151
+ public:
152
+ constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
153
+ size_t num_args = 0) noexcept;
154
+ basic_format_parse_context(const basic_format_parse_context&) = delete;
155
+ basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
156
+
157
+ constexpr const_iterator begin() const noexcept;
158
+ constexpr const_iterator end() const noexcept;
159
+ constexpr void advance_to(const_iterator it);
160
+
161
+ constexpr size_t next_arg_id();
162
+ constexpr void check_arg_id(size_t id);
163
+ };
164
+ }
165
+ ```
166
+
167
+ An instance of `basic_format_parse_context` holds the format string
168
+ parsing state consisting of the format string range being parsed and the
169
+ argument counter for automatic indexing.
170
+
171
+ ``` cpp
172
+ constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
173
+ size_t num_args = 0) noexcept;
174
+ ```
175
+
176
+ *Effects:* Initializes `begin_` with `fmt.begin()`, `end_` with
177
+ `fmt.end()`, `indexing_` with `unknown`, `next_arg_id_` with `0`, and
178
+ `num_args_` with `num_args`.
179
+
180
+ ``` cpp
181
+ constexpr const_iterator begin() const noexcept;
182
+ ```
183
+
184
+ *Returns:* `begin_`.
185
+
186
+ ``` cpp
187
+ constexpr const_iterator end() const noexcept;
188
+ ```
189
+
190
+ *Returns:* `end_`.
191
+
192
+ ``` cpp
193
+ constexpr void advance_to(const_iterator it);
194
+ ```
195
+
196
+ *Preconditions:* `end()` is reachable from `it`.
197
+
198
+ *Effects:* Equivalent to: `begin_ = it;`
199
+
200
+ ``` cpp
201
+ constexpr size_t next_arg_id();
202
+ ```
203
+
204
+ *Effects:* If `indexing_ != manual`, equivalent to:
205
+
206
+ ``` cpp
207
+ if (indexing_ == unknown)
208
+ indexing_ = automatic;
209
+ return next_arg_id_++;
210
+ ```
211
+
212
+ *Throws:* `format_error` if `indexing_ == manual` which indicates mixing
213
+ of automatic and manual argument indexing.
214
+
215
+ ``` cpp
216
+ constexpr void check_arg_id(size_t id);
217
+ ```
218
+
219
+ *Effects:* If `indexing_ != automatic`, equivalent to:
220
+
221
+ ``` cpp
222
+ if (indexing_ == unknown)
223
+ indexing_ = manual;
224
+ ```
225
+
226
+ *Throws:* `format_error` if `indexing_ == automatic` which indicates
227
+ mixing of automatic and manual argument indexing.
228
+
229
+ *Remarks:* Call expressions where `id >= num_args_` are not core
230
+ constant expressions [[expr.const]].
231
+
232
+ #### Class template `basic_format_context` <a id="format.context">[[format.context]]</a>
233
+
234
+ ``` cpp
235
+ namespace std {
236
+ template<class Out, class charT>
237
+ class basic_format_context {
238
+ basic_format_args<basic_format_context> args_; // exposition only
239
+ Out out_; // exposition only
240
+
241
+ public:
242
+ using iterator = Out;
243
+ using char_type = charT;
244
+ template<class T> using formatter_type = formatter<T, charT>;
245
+
246
+ basic_format_arg<basic_format_context> arg(size_t id) const;
247
+ std::locale locale();
248
+
249
+ iterator out();
250
+ void advance_to(iterator it);
251
+ };
252
+ }
253
+ ```
254
+
255
+ An instance of `basic_format_context` holds formatting state consisting
256
+ of the formatting arguments and the output iterator.
257
+
258
+ `Out` shall model `output_iterator<const charT&>`.
259
+
260
+ `format_context` is an alias for a specialization of
261
+ `basic_format_context` with an output iterator that appends to `string`,
262
+ such as `back_insert_iterator<string>`. Similarly, `wformat_context` is
263
+ an alias for a specialization of `basic_format_context` with an output
264
+ iterator that appends to `wstring`.
265
+
266
+ [*Note 1*: For a given type `charT`, implementations are encouraged to
267
+ provide a single instantiation of `basic_format_context` for appending
268
+ to `basic_string<charT>`, `vector<charT>`, or any other container with
269
+ contiguous storage by wrapping those in temporary objects with a uniform
270
+ interface (such as a `span<charT>`) and polymorphic
271
+ reallocation. — *end note*]
272
+
273
+ ``` cpp
274
+ basic_format_arg<basic_format_context> arg(size_t id) const;
275
+ ```
276
+
277
+ *Returns:* `args_.get(id)`.
278
+
279
+ ``` cpp
280
+ std::locale locale();
281
+ ```
282
+
283
+ *Returns:* The locale passed to the formatting function if the latter
284
+ takes one, and `std::locale()` otherwise.
285
+
286
+ ``` cpp
287
+ iterator out();
288
+ ```
289
+
290
+ *Returns:* `out_`.
291
+
292
+ ``` cpp
293
+ void advance_to(iterator it);
294
+ ```
295
+
296
+ *Effects:* Equivalent to: `out_ = it;`
297
+
298
+ [*Example 1*:
299
+
300
+ ``` cpp
301
+ struct S { int value; };
302
+
303
+ template<> struct std::formatter<S> {
304
+ size_t width_arg_id = 0;
305
+
306
+ // Parses a width argument id in the format { digit }.
307
+ constexpr auto parse(format_parse_context& ctx) {
308
+ auto iter = ctx.begin();
309
+ auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; };
310
+ if (get_char() != '{')
311
+ return iter;
312
+ ++iter;
313
+ char c = get_char();
314
+ if (!isdigit(c) || (++iter, get_char()) != '}')
315
+ throw format_error("invalid format");
316
+ width_arg_id = c - '0';
317
+ ctx.check_arg_id(width_arg_id);
318
+ return ++iter;
319
+ }
320
+
321
+ // Formats an S with width given by the argument width_arg_id.
322
+ auto format(S s, format_context& ctx) {
323
+ int width = visit_format_arg([](auto value) -> int {
324
+ if constexpr (!is_integral_v<decltype(value)>)
325
+ throw format_error("width is not integral");
326
+ else if (value < 0 || value > numeric_limits<int>::max())
327
+ throw format_error("invalid width");
328
+ else
329
+ return value;
330
+ }, ctx.arg(width_arg_id));
331
+ return format_to(ctx.out(), "{0:x<{1}}", s.value, width);
332
+ }
333
+ };
334
+
335
+ std::string s = std::format("{0:{1}}", S{42}, 10); // value of s is "xxxxxxxx42"
336
+ ```
337
+
338
+ — *end example*]
339
+