xref: /llvm-project-15.0.7/libcxx/include/format (revision 3cd4531b)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_FORMAT
11#define _LIBCPP_FORMAT
12
13/*
14
15namespace std {
16  // [format.context], class template basic_format_context
17  template<class Out, class charT> class basic_format_context;
18  using format_context = basic_format_context<unspecified, char>;
19  using wformat_context = basic_format_context<unspecified, wchar_t>;
20
21  // [format.args], class template basic_format_args
22  template<class Context> class basic_format_args;
23  using format_args = basic_format_args<format_context>;
24  using wformat_args = basic_format_args<wformat_context>;
25
26  // [format.functions], formatting functions
27  template<class... Args>
28    string format(string_view fmt, const Args&... args);
29  template<class... Args>
30    wstring format(wstring_view fmt, const Args&... args);
31  template<class... Args>
32    string format(const locale& loc, string_view fmt, const Args&... args);
33  template<class... Args>
34    wstring format(const locale& loc, wstring_view fmt, const Args&... args);
35
36  string vformat(string_view fmt, format_args args);
37  wstring vformat(wstring_view fmt, wformat_args args);
38  string vformat(const locale& loc, string_view fmt, format_args args);
39  wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
40
41  template<class Out, class... Args>
42    Out format_to(Out out, string_view fmt, const Args&... args);
43  template<class Out, class... Args>
44    Out format_to(Out out, wstring_view fmt, const Args&... args);
45  template<class Out, class... Args>
46    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
47  template<class Out, class... Args>
48    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
49
50  template<class Out>
51    Out vformat_to(Out out, string_view fmt, format_args args);
52  template<class Out>
53    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
54  template<class Out>
55    Out vformat_to(Out out, const locale& loc, string_view fmt,
56                   format_args char> args);
57  template<class Out>
58    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
59                   wformat_args args);
60
61  template<class Out> struct format_to_n_result {
62    Out out;
63    iter_difference_t<Out> size;
64  };
65  template<class Out, class... Args>
66    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
67                                        string_view fmt, const Args&... args);
68  template<class Out, class... Args>
69    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
70                                        wstring_view fmt, const Args&... args);
71  template<class Out, class... Args>
72    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
73                                        const locale& loc, string_view fmt,
74                                        const Args&... args);
75  template<class Out, class... Args>
76    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
77                                        const locale& loc, wstring_view fmt,
78                                        const Args&... args);
79
80  template<class... Args>
81    size_t formatted_size(string_view fmt, const Args&... args);
82  template<class... Args>
83    size_t formatted_size(wstring_view fmt, const Args&... args);
84  template<class... Args>
85    size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
86  template<class... Args>
87    size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
88
89  // [format.formatter], formatter
90  template<class T, class charT = char> struct formatter;
91
92  // [format.parse.ctx], class template basic_format_parse_context
93  template<class charT> class basic_format_parse_context;
94  using format_parse_context = basic_format_parse_context<char>;
95  using wformat_parse_context = basic_format_parse_context<wchar_t>;
96
97  // [format.arguments], arguments
98  // [format.arg], class template basic_format_arg
99  template<class Context> class basic_format_arg;
100
101  template<class Visitor, class Context>
102    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
103
104  // [format.arg.store], class template format-arg-store
105  template<class Context, class... Args> struct format-arg-store;      // exposition only
106
107  template<class Context = format_context, class... Args>
108    format-arg-store<Context, Args...>
109      make_format_args(const Args&... args);
110  template<class... Args>
111    format-arg-store<wformat_context, Args...>
112      make_wformat_args(const Args&... args);
113
114  // [format.error], class format_error
115  class format_error;
116}
117
118*/
119
120#include <__assert> // all public C++ headers provide the assertion handler
121// Make sure all feature-test macros are available.
122#include <version>
123// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
124#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
125
126#include <__algorithm/clamp.h>
127#include <__config>
128#include <__debug>
129#include <__format/buffer.h>
130#include <__format/concepts.h>
131#include <__format/enable_insertable.h>
132#include <__format/format_arg.h>
133#include <__format/format_arg_store.h>
134#include <__format/format_args.h>
135#include <__format/format_context.h>
136#include <__format/format_error.h>
137#include <__format/format_fwd.h>
138#include <__format/format_parse_context.h>
139#include <__format/format_string.h>
140#include <__format/format_to_n_result.h>
141#include <__format/formatter.h>
142#include <__format/formatter_bool.h>
143#include <__format/formatter_char.h>
144#include <__format/formatter_floating_point.h>
145#include <__format/formatter_integer.h>
146#include <__format/formatter_pointer.h>
147#include <__format/formatter_string.h>
148#include <__format/parser_std_format_spec.h>
149#include <__iterator/incrementable_traits.h>
150#include <__variant/monostate.h>
151#include <array>
152#include <concepts>
153#include <string>
154#include <string_view>
155#include <type_traits>
156
157#ifndef _LIBCPP_HAS_NO_LOCALIZATION
158#include <locale>
159#endif
160
161#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
162#  pragma GCC system_header
163#endif
164
165_LIBCPP_BEGIN_NAMESPACE_STD
166
167#if _LIBCPP_STD_VER > 17
168
169// TODO FMT Move the implementation in this file to its own granular headers.
170
171// TODO FMT Evaluate which templates should be external templates. This
172// improves the efficiency of the header. However since the header is still
173// under heavy development and not all classes are stable it makes no sense
174// to do this optimization now.
175
176using format_args = basic_format_args<format_context>;
177#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
178using wformat_args = basic_format_args<wformat_context>;
179#endif
180
181// TODO FMT This helper wrapper can probably be removed after P2418 has been
182// implemented.
183template <class _Context, class... _Args>
184_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
185__make_format_args(_Args&&... __args) {
186  return _VSTD::__format_arg_store<_Context, _Args...>(
187      _VSTD::forward<_Args>(__args)...);
188}
189
190// TODO FMT After P2418 specify the return type instead of using auto.
191template <class _Context = format_context, class... _Args>
192_LIBCPP_HIDE_FROM_ABI auto make_format_args(const _Args&... __args) {
193  return _VSTD::__make_format_args<_Context>(__args...);
194}
195
196#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
197// TODO FMT After P2418 specify the return type instead of using auto.
198template <class... _Args>
199_LIBCPP_HIDE_FROM_ABI auto make_wformat_args(const _Args&... __args) {
200  return _VSTD::make_format_args<wformat_context>(__args...);
201}
202#endif
203
204namespace __format {
205
206template <class _CharT, class _ParseCtx, class _Ctx>
207_LIBCPP_HIDE_FROM_ABI const _CharT*
208__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
209                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
210  __format::__parse_number_result __r =
211      __format::__parse_arg_id(__begin, __end, __parse_ctx);
212
213  switch (*__r.__ptr) {
214  case _CharT(':'):
215    // The arg-id has a format-specifier, advance the input to the format-spec.
216    __parse_ctx.advance_to(__r.__ptr + 1);
217    break;
218  case _CharT('}'):
219    // The arg-id has no format-specifier.
220    __parse_ctx.advance_to(__r.__ptr);
221    break;
222  default:
223    __throw_format_error(
224        "The replacement field arg-id should terminate at a ':' or '}'");
225  }
226
227  _VSTD::visit_format_arg(
228      [&](auto __arg) {
229        if constexpr (same_as<decltype(__arg), monostate>)
230          __throw_format_error("Argument index out of bounds");
231        else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
232          __arg.format(__parse_ctx, __ctx);
233        else {
234          formatter<decltype(__arg), _CharT> __formatter;
235          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
236          __ctx.advance_to(__formatter.format(__arg, __ctx));
237        }
238      },
239      __ctx.arg(__r.__value));
240
241  __begin = __parse_ctx.begin();
242  if (__begin == __end || *__begin != _CharT('}'))
243    __throw_format_error("The replacement field misses a terminating '}'");
244
245  return ++__begin;
246}
247
248template <class _ParseCtx, class _Ctx>
249_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
250__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
251  using _CharT = typename _ParseCtx::char_type;
252  static_assert(same_as<typename _Ctx::char_type, _CharT>);
253
254  const _CharT* __begin = __parse_ctx.begin();
255  const _CharT* __end = __parse_ctx.end();
256  typename _Ctx::iterator __out_it = __ctx.out();
257  while (__begin != __end) {
258    switch (*__begin) {
259    case _CharT('{'):
260      ++__begin;
261      if (__begin == __end)
262        __throw_format_error("The format string terminates at a '{'");
263
264      if (*__begin != _CharT('{')) [[likely]] {
265        __ctx.advance_to(_VSTD::move(__out_it));
266        __begin =
267            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
268        __out_it = __ctx.out();
269
270        // The output is written and __begin points to the next character. So
271        // start the next iteration.
272        continue;
273      }
274      // The string is an escape character.
275      break;
276
277    case _CharT('}'):
278      ++__begin;
279      if (__begin == __end || *__begin != _CharT('}'))
280        __throw_format_error(
281            "The format string contains an invalid escape sequence");
282
283      break;
284    }
285
286    // Copy the character to the output verbatim.
287    *__out_it++ = *__begin++;
288  }
289  return __out_it;
290}
291
292} // namespace __format
293
294template <class _OutIt, class _CharT, class _FormatOutIt>
295requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
296    __vformat_to(
297        _OutIt __out_it, basic_string_view<_CharT> __fmt,
298        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
299  if constexpr (same_as<_OutIt, _FormatOutIt>)
300    return _VSTD::__format::__vformat_to(
301        basic_format_parse_context{__fmt, __args.__size()},
302        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
303  else {
304    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
305    _VSTD::__format::__vformat_to(
306        basic_format_parse_context{__fmt, __args.__size()},
307        _VSTD::__format_context_create(__buffer.make_output_iterator(),
308                                       __args));
309    return _VSTD::move(__buffer).out();
310  }
311}
312
313// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
314// https://reviews.llvm.org/D110499#inline-1180704
315// TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
316template <output_iterator<const char&> _OutIt>
317_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
318vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
319  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
320}
321
322#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
323template <output_iterator<const wchar_t&> _OutIt>
324_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
325vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
326  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
327}
328#endif
329
330template <output_iterator<const char&> _OutIt, class... _Args>
331_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
332format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
333  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
334                           _VSTD::make_format_args(__args...));
335}
336
337#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
338template <output_iterator<const wchar_t&> _OutIt, class... _Args>
339_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
340format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
341  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
342                           _VSTD::make_wformat_args(__args...));
343}
344#endif
345
346_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
347vformat(string_view __fmt, format_args __args) {
348  string __res;
349  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
350  return __res;
351}
352
353#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
354_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
355vformat(wstring_view __fmt, wformat_args __args) {
356  wstring __res;
357  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
358  return __res;
359}
360#endif
361
362template <class... _Args>
363_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
364format(string_view __fmt, const _Args&... __args) {
365  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
366}
367
368#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
369template <class... _Args>
370_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
371format(wstring_view __fmt, const _Args&... __args) {
372  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
373}
374#endif
375
376template <class _Context, class _OutIt, class _CharT>
377_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
378                                                                basic_string_view<_CharT> __fmt,
379                                                                basic_format_args<_Context> __args) {
380  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
381  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
382                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
383  return _VSTD::move(__buffer).result();
384}
385
386template <output_iterator<const char&> _OutIt, class... _Args>
387_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
388format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, const _Args&... __args) {
389  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_format_args(__args...));
390}
391
392#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
393template <output_iterator<const wchar_t&> _OutIt, class... _Args>
394_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
395format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, const _Args&... __args) {
396  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_wformat_args(__args...));
397}
398#endif
399
400template <class _CharT>
401_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
402  __format::__formatted_size_buffer<_CharT> __buffer;
403  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
404                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
405  return _VSTD::move(__buffer).result();
406}
407
408template <class... _Args>
409_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(string_view __fmt,
410                                                                                              const _Args&... __args) {
411  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_format_args(__args...)});
412}
413
414#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
415template <class... _Args>
416_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(wstring_view __fmt,
417                                                                                              const _Args&... __args) {
418  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
419}
420#endif
421
422#ifndef _LIBCPP_HAS_NO_LOCALIZATION
423
424template <class _OutIt, class _CharT, class _FormatOutIt>
425requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
426    __vformat_to(
427        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
428        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
429  if constexpr (same_as<_OutIt, _FormatOutIt>)
430    return _VSTD::__format::__vformat_to(
431        basic_format_parse_context{__fmt, __args.__size()},
432        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
433                                       _VSTD::move(__loc)));
434  else {
435    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
436    _VSTD::__format::__vformat_to(
437        basic_format_parse_context{__fmt, __args.__size()},
438        _VSTD::__format_context_create(__buffer.make_output_iterator(),
439                                       __args, _VSTD::move(__loc)));
440    return _VSTD::move(__buffer).out();
441  }
442}
443
444template <output_iterator<const char&> _OutIt>
445_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
446    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
447  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
448                             __args);
449}
450
451#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
452template <output_iterator<const wchar_t&> _OutIt>
453_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
454    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
455  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
456                             __args);
457}
458#endif
459
460template <output_iterator<const char&> _OutIt, class... _Args>
461_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
462    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
463  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
464                           _VSTD::make_format_args(__args...));
465}
466
467#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
468template <output_iterator<const wchar_t&> _OutIt, class... _Args>
469_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
470    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
471  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
472                           _VSTD::make_wformat_args(__args...));
473}
474#endif
475
476_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
477vformat(locale __loc, string_view __fmt, format_args __args) {
478  string __res;
479  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
480                    __args);
481  return __res;
482}
483
484#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
485_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
486vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
487  wstring __res;
488  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
489                    __args);
490  return __res;
491}
492#endif
493
494template <class... _Args>
495_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
496format(locale __loc, string_view __fmt, const _Args&... __args) {
497  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
498                        _VSTD::make_format_args(__args...));
499}
500
501#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
502template <class... _Args>
503_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
504format(locale __loc, wstring_view __fmt, const _Args&... __args) {
505  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
506                        _VSTD::make_wformat_args(__args...));
507}
508#endif
509
510template <class _Context, class _OutIt, class _CharT>
511_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
512                                                                locale __loc, basic_string_view<_CharT> __fmt,
513                                                                basic_format_args<_Context> __args) {
514  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
515  _VSTD::__format::__vformat_to(
516      basic_format_parse_context{__fmt, __args.__size()},
517      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
518  return _VSTD::move(__buffer).result();
519}
520
521template <output_iterator<const char&> _OutIt, class... _Args>
522_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
523format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, string_view __fmt, const _Args&... __args) {
524  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
525                                               _VSTD::make_format_args(__args...));
526}
527
528#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
529template <output_iterator<const wchar_t&> _OutIt, class... _Args>
530_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
531format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wstring_view __fmt, const _Args&... __args) {
532  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
533                                                _VSTD::make_wformat_args(__args...));
534}
535#endif
536
537template <class _CharT>
538_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
539  __format::__formatted_size_buffer<_CharT> __buffer;
540  _VSTD::__format::__vformat_to(
541      basic_format_parse_context{__fmt, __args.__size()},
542      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
543  return _VSTD::move(__buffer).result();
544}
545
546template <class... _Args>
547_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
548                                                                                              string_view __fmt,
549                                                                                              const _Args&... __args) {
550  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
551}
552
553#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
554template <class... _Args>
555_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
556                                                                                              wstring_view __fmt,
557                                                                                              const _Args&... __args) {
558  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
559}
560#endif
561
562#endif // _LIBCPP_HAS_NO_LOCALIZATION
563
564#endif //_LIBCPP_STD_VER > 17
565
566_LIBCPP_END_NAMESPACE_STD
567
568#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
569
570#endif // _LIBCPP_FORMAT
571