2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_FORMAT
11 #define _LIBCPP_FORMAT
16 // [format.context], class template basic_format_context
17 template<class Out, class charT>
18 class basic_format_context {
19 basic_format_args<basic_format_context> args_; // exposition only
20 Out out_; // exposition only
24 using char_type = charT;
25 template<class T> using formatter_type = formatter<T, charT>;
27 basic_format_arg<basic_format_context> arg(size_t id) const;
31 void advance_to(iterator it);
33 using format_context = basic_format_context<unspecified, char>;
34 using wformat_context = basic_format_context<unspecified, wchar_t>;
36 // [format.args], class template basic_format_args
37 template<class Context>
38 class basic_format_args {
39 size_t size_; // exposition only
40 const basic_format_arg<Context>* data_; // exposition only
43 basic_format_args() noexcept;
45 template<class... Args>
46 basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
48 basic_format_arg<Context> get(size_t i) const noexcept;
50 using format_args = basic_format_args<format_context>;
51 using wformat_args = basic_format_args<wformat_context>;
54 template<class Out, class charT>
55 using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
57 // [format.functions], formatting functions
58 template<class... Args>
59 string format(string_view fmt, const Args&... args);
60 template<class... Args>
61 wstring format(wstring_view fmt, const Args&... args);
62 template<class... Args>
63 string format(const locale& loc, string_view fmt, const Args&... args);
64 template<class... Args>
65 wstring format(const locale& loc, wstring_view fmt, const Args&... args);
67 string vformat(string_view fmt, format_args args);
68 wstring vformat(wstring_view fmt, wformat_args args);
69 string vformat(const locale& loc, string_view fmt, format_args args);
70 wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
72 template<class Out, class... Args>
73 Out format_to(Out out, string_view fmt, const Args&... args);
74 template<class Out, class... Args>
75 Out format_to(Out out, wstring_view fmt, const Args&... args);
76 template<class Out, class... Args>
77 Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
78 template<class Out, class... Args>
79 Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
82 Out vformat_to(Out out, string_view fmt,
83 format_args_t<type_identity_t<Out>, char> args);
85 Out vformat_to(Out out, wstring_view fmt,
86 format_args_t<type_identity_t<Out>, wchar_t> args);
88 Out vformat_to(Out out, const locale& loc, string_view fmt,
89 format_args_t<type_identity_t<Out>, char> args);
91 Out vformat_to(Out out, const locale& loc, wstring_view fmt,
92 format_args_t<type_identity_t<Out>, wchar_t> args);
94 template<class Out> struct format_to_n_result {
96 iter_difference_t<Out> size;
99 template<class Out, class... Args>
100 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
101 string_view fmt, const Args&... args);
102 template<class Out, class... Args>
103 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
104 wstring_view fmt, const Args&... args);
105 template<class Out, class... Args>
106 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
107 const locale& loc, string_view fmt,
108 const Args&... args);
109 template<class Out, class... Args>
110 format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
111 const locale& loc, wstring_view fmt,
112 const Args&... args);
114 template<class... Args>
115 size_t formatted_size(string_view fmt, const Args&... args);
116 template<class... Args>
117 size_t formatted_size(wstring_view fmt, const Args&... args);
118 template<class... Args>
119 size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
120 template<class... Args>
121 size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
123 // [format.formatter], formatter
124 template<> struct formatter<char, char>;
125 template<> struct formatter<char, wchar_t>;
126 template<> struct formatter<wchar_t, wchar_t>;
128 template<> struct formatter<charT*, charT>;
129 template<> struct formatter<const charT*, charT>;
130 template<size_t N> struct formatter<const charT[N], charT>;
131 template<class traits, class Allocator>
132 struct formatter<basic_string<charT, traits, Allocator>, charT>;
133 template<class traits>
134 struct formatter<basic_string_view<charT, traits>, charT>;
136 // [format.parse.ctx], class template basic_format_parse_context
137 template<class charT>
138 class basic_format_parse_context {
140 using char_type = charT;
141 using const_iterator = typename basic_string_view<charT>::const_iterator;
142 using iterator = const_iterator;
145 iterator begin_; // exposition only
146 iterator end_; // exposition only
147 enum indexing { unknown, manual, automatic }; // exposition only
148 indexing indexing_; // exposition only
149 size_t next_arg_id_; // exposition only
150 size_t num_args_; // exposition only
153 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
154 size_t num_args = 0) noexcept;
155 basic_format_parse_context(const basic_format_parse_context&) = delete;
156 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
158 constexpr const_iterator begin() const noexcept;
159 constexpr const_iterator end() const noexcept;
160 constexpr void advance_to(const_iterator it);
162 constexpr size_t next_arg_id();
163 constexpr void check_arg_id(size_t id);
165 using format_parse_context = basic_format_parse_context<char>;
166 using wformat_parse_context = basic_format_parse_context<wchar_t>;
168 // [format.arguments], arguments
169 // [format.arg], class template basic_format_arg
170 template<class Context>
171 class basic_format_arg {
176 using char_type = typename Context::char_type; // exposition only
178 variant<monostate, bool, char_type,
179 int, unsigned int, long long int, unsigned long long int,
180 float, double, long double,
181 const char_type*, basic_string_view<char_type>,
182 const void*, handle> value; // exposition only
184 template<class T> explicit basic_format_arg(const T& v) noexcept; // exposition only
185 explicit basic_format_arg(float n) noexcept; // exposition only
186 explicit basic_format_arg(double n) noexcept; // exposition only
187 explicit basic_format_arg(long double n) noexcept; // exposition only
188 explicit basic_format_arg(const char_type* s); // exposition only
190 template<class traits>
191 explicit basic_format_arg(
192 basic_string_view<char_type, traits> s) noexcept; // exposition only
194 template<class traits, class Allocator>
195 explicit basic_format_arg(
196 const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only
198 explicit basic_format_arg(nullptr_t) noexcept; // exposition only
201 explicit basic_format_arg(const T* p) noexcept; // exposition only
204 basic_format_arg() noexcept;
206 explicit operator bool() const noexcept;
209 template<class Visitor, class Context>
210 see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
212 // [format.arg.store], class template format-arg-store
213 template<class Context, class... Args>
214 struct format-arg-store { // exposition only
215 array<basic_format_arg<Context>, sizeof...(Args)> args;
218 template<class Context = format_context, class... Args>
219 format-arg-store<Context, Args...>
220 make_format_args(const Args&... args);
221 template<class... Args>
222 format-arg-store<wformat_context, Args...>
223 make_wformat_args(const Args&... args);
225 // [format.error], class format_error
226 class format_error : public runtime_error {
228 explicit format_error(const string& what_arg);
229 explicit format_error(const char* what_arg);
232 // [format.parse.ctx], class template basic_format_parse_context
233 template<class charT>
234 class basic_format_parse_context {
236 using char_type = charT;
237 using const_iterator = typename basic_string_view<charT>::const_iterator;
238 using iterator = const_iterator;
241 iterator begin_; // exposition only
242 iterator end_; // exposition only
243 enum indexing { unknown, manual, automatic }; // exposition only
244 indexing indexing_; // exposition only
245 size_t next_arg_id_; // exposition only
246 size_t num_args_; // exposition only
249 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
250 size_t num_args = 0) noexcept;
251 basic_format_parse_context(const basic_format_parse_context&) = delete;
252 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
254 constexpr const_iterator begin() const noexcept;
255 constexpr const_iterator end() const noexcept;
256 constexpr void advance_to(const_iterator it);
258 constexpr size_t next_arg_id();
259 constexpr void check_arg_id(size_t id);
261 using format_parse_context = basic_format_parse_context<char>;
262 using wformat_parse_context = basic_format_parse_context<wchar_t>;
267 // Make sure all feature-test macros are available.
269 // Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
270 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
274 #include <__format/format_arg.h>
275 #include <__format/format_args.h>
276 #include <__format/format_context.h>
277 #include <__format/format_error.h>
278 #include <__format/format_fwd.h>
279 #include <__format/format_parse_context.h>
280 #include <__format/format_string.h>
281 #include <__format/format_to_n_result.h>
282 #include <__format/formatter.h>
283 #include <__format/formatter_bool.h>
284 #include <__format/formatter_char.h>
285 #include <__format/formatter_integer.h>
286 #include <__format/formatter_string.h>
287 #include <__format/parser_std_format_spec.h>
288 #include <__variant/monostate.h>
292 #include <string_view>
293 #include <type_traits>
295 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
299 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
300 #pragma GCC system_header
304 #include <__undef_macros>
306 _LIBCPP_BEGIN_NAMESPACE_STD
308 #if _LIBCPP_STD_VER > 17
310 // TODO FMT Remove this once we require compilers with proper C++20 support.
311 // If the compiler has no concepts support, the format header will be disabled.
312 // Without concepts support enable_if needs to be used and that too much effort
313 // to support compilers with partial C++20 support.
314 #if !defined(_LIBCPP_HAS_NO_CONCEPTS)
316 // TODO FMT Move the implementation in this file to its own granular headers.
318 // TODO FMT Evaluate which templates should be external templates. This
319 // improves the efficiency of the header. However since the header is still
320 // under heavy development and not all classes are stable it makes no sense
321 // to do this optimization now.
323 using format_args = basic_format_args<format_context>;
324 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
325 using wformat_args = basic_format_args<wformat_context>;
328 template <class _OutIt, class _CharT>
329 using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
331 template <class _Context, class... _Args>
332 struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
333 // TODO FMT Use a built-in array.
334 array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
337 template <class _Context = format_context, class... _Args>
338 _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
339 make_format_args(const _Args&... __args) {
340 return {basic_format_arg<_Context>(__args)...};
343 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
344 template <class... _Args>
345 _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
346 make_wformat_args(const _Args&... __args) {
347 return _VSTD::make_format_args<wformat_context>(__args...);
353 template <class _CharT, class _ParseCtx, class _Ctx>
354 _LIBCPP_HIDE_FROM_ABI const _CharT*
355 __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
356 _ParseCtx& __parse_ctx, _Ctx& __ctx) {
357 __format::__parse_number_result __r =
358 __format::__parse_arg_id(__begin, __end, __parse_ctx);
360 switch (*__r.__ptr) {
362 // The arg-id has a format-specifier, advance the input to the format-spec.
363 __parse_ctx.advance_to(__r.__ptr + 1);
366 // The arg-id has no format-specifier.
367 __parse_ctx.advance_to(__r.__ptr);
370 __throw_format_error(
371 "The replacement field arg-id should terminate at a ':' or '}'");
374 _VSTD::visit_format_arg(
376 if constexpr (same_as<decltype(__arg), monostate>)
377 __throw_format_error("Argument index out of bounds");
379 formatter<decltype(__arg), _CharT> __formatter;
380 __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
381 __ctx.advance_to(__formatter.format(__arg, __ctx));
384 __ctx.arg(__r.__value));
386 __begin = __parse_ctx.begin();
387 if (__begin == __end || *__begin != _CharT('}'))
388 __throw_format_error("The replacement field misses a terminating '}'");
393 template <class _ParseCtx, class _Ctx>
394 _LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
395 __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
396 using _CharT = typename _ParseCtx::char_type;
397 static_assert(same_as<typename _Ctx::char_type, _CharT>);
399 const _CharT* __begin = __parse_ctx.begin();
400 const _CharT* __end = __parse_ctx.end();
401 typename _Ctx::iterator __out_it = __ctx.out();
402 while (__begin != __end) {
406 if (__begin == __end)
407 __throw_format_error("The format string terminates at a '{'");
409 if (*__begin != _CharT('{')) [[likely]] {
410 __ctx.advance_to(_VSTD::move(__out_it));
412 __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
413 __out_it = __ctx.out();
415 // The output is written and __begin points to the next character. So
416 // start the next iteration.
419 // The string is an escape character.
424 if (__begin == __end || *__begin != _CharT('}'))
425 __throw_format_error(
426 "The format string contains an invalid escape sequence");
431 // Copy the character to the output verbatim.
432 *__out_it++ = *__begin++;
437 } // namespace __format
439 template <class _OutIt, class _CharT>
440 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
441 __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
442 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
443 return __format::__vformat_to(
444 basic_format_parse_context{__fmt, __args.__size()},
445 _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
448 template <output_iterator<const char&> _OutIt>
449 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
450 vformat_to(_OutIt __out_it, string_view __fmt,
451 format_args_t<type_identity_t<_OutIt>, char> __args) {
452 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
455 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
456 template <output_iterator<const wchar_t&> _OutIt>
457 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
458 vformat_to(_OutIt __out_it, wstring_view __fmt,
459 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
460 return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
464 template <output_iterator<const char&> _OutIt, class... _Args>
465 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
466 format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
467 return _VSTD::vformat_to(
468 _VSTD::move(__out_it), __fmt,
469 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
472 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
473 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
474 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
475 format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
476 return _VSTD::vformat_to(
477 _VSTD::move(__out_it), __fmt,
478 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
483 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
484 vformat(string_view __fmt, format_args __args) {
486 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
490 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
491 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
492 vformat(wstring_view __fmt, wformat_args __args) {
494 _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
499 template <class... _Args>
500 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
501 format(string_view __fmt, const _Args&... __args) {
502 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
505 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
506 template <class... _Args>
507 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
508 format(wstring_view __fmt, const _Args&... __args) {
509 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
513 template <output_iterator<const char&> _OutIt, class... _Args>
514 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
515 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
516 const _Args&... __args) {
517 // TODO FMT Improve PoC: using std::string is inefficient.
518 string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
519 iter_difference_t<_OutIt> __s = __str.size();
520 iter_difference_t<_OutIt> __m =
521 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
522 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
523 return {_VSTD::move(__out_it), __s};
526 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
527 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
528 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
529 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
530 const _Args&... __args) {
531 // TODO FMT Improve PoC: using std::string is inefficient.
532 wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
533 iter_difference_t<_OutIt> __s = __str.size();
534 iter_difference_t<_OutIt> __m =
535 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
536 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
537 return {_VSTD::move(__out_it), __s};
541 template <class... _Args>
542 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
543 formatted_size(string_view __fmt, const _Args&... __args) {
544 // TODO FMT Improve PoC: using std::string is inefficient.
545 return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
548 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
549 template <class... _Args>
550 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
551 formatted_size(wstring_view __fmt, const _Args&... __args) {
552 // TODO FMT Improve PoC: using std::string is inefficient.
553 return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
557 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
559 template <class _OutIt, class _CharT>
560 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
561 __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
562 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
563 return __format::__vformat_to(
564 basic_format_parse_context{__fmt, __args.__size()},
565 _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
566 _VSTD::move(__loc)));
569 template <output_iterator<const char&> _OutIt>
570 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
571 vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
572 format_args_t<type_identity_t<_OutIt>, char> __args) {
573 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
577 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
578 template <output_iterator<const wchar_t&> _OutIt>
579 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
580 vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
581 format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
582 return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
587 template <output_iterator<const char&> _OutIt, class... _Args>
588 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
589 _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
590 return _VSTD::vformat_to(
591 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
592 _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
595 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
596 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
597 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
598 _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
599 return _VSTD::vformat_to(
600 _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
601 _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
606 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
607 vformat(locale __loc, string_view __fmt, format_args __args) {
609 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
614 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
615 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
616 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
618 _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
624 template <class... _Args>
625 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
626 format(locale __loc, string_view __fmt, const _Args&... __args) {
627 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
628 _VSTD::make_format_args(__args...));
631 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
632 template <class... _Args>
633 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
634 format(locale __loc, wstring_view __fmt, const _Args&... __args) {
635 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
636 _VSTD::make_wformat_args(__args...));
640 template <output_iterator<const char&> _OutIt, class... _Args>
641 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
642 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
643 string_view __fmt, const _Args&... __args) {
644 // TODO FMT Improve PoC: using std::string is inefficient.
645 string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
646 _VSTD::make_format_args(__args...));
647 iter_difference_t<_OutIt> __s = __str.size();
648 iter_difference_t<_OutIt> __m =
649 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
650 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
651 return {_VSTD::move(__out_it), __s};
654 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
655 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
656 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
657 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
658 wstring_view __fmt, const _Args&... __args) {
659 // TODO FMT Improve PoC: using std::string is inefficient.
660 wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
661 _VSTD::make_wformat_args(__args...));
662 iter_difference_t<_OutIt> __s = __str.size();
663 iter_difference_t<_OutIt> __m =
664 _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
665 __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
666 return {_VSTD::move(__out_it), __s};
670 template <class... _Args>
671 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
672 formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
673 // TODO FMT Improve PoC: using std::string is inefficient.
674 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
675 _VSTD::make_format_args(__args...))
679 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
680 template <class... _Args>
681 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
682 formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
683 // TODO FMT Improve PoC: using std::string is inefficient.
684 return _VSTD::vformat(_VSTD::move(__loc), __fmt,
685 _VSTD::make_wformat_args(__args...))
690 #endif // _LIBCPP_HAS_NO_LOCALIZATION
692 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
693 #endif //_LIBCPP_STD_VER > 17
695 _LIBCPP_END_NAMESPACE_STD
699 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
701 #endif // _LIBCPP_FORMAT