| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | // Formatting library for C++ - the standard API implementation | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Copyright (c) 2012 - present, Victor Zverovich | 
					
						
							|  |  |  | // All rights reserved. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // For the license information refer to format.h. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef FMT_FORMAT_ | 
					
						
							|  |  |  | #define FMT_FORMAT_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <variant> | 
					
						
							|  |  |  | #include "fmt/format.h" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This implementation verifies the correctness of the standard API proposed in | 
					
						
							|  |  |  | // P0645 Text Formatting and is optimized for copy-pasting from the paper, not | 
					
						
							|  |  |  | // for efficiency or readability. An efficient implementation should not use | 
					
						
							|  |  |  | // std::variant and should store packed argument type tags separately from | 
					
						
							|  |  |  | // values in basic_format_args for small number of arguments. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | template<class T> | 
					
						
							|  |  |  | constexpr bool Integral = is_integral_v<T>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class O> | 
					
						
							|  |  |  |   using iter_difference_t = ptrdiff_t; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.syn | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   // [format.error], class format_error | 
					
						
							|  |  |  |   class format_error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // [format.formatter], formatter | 
					
						
							|  |  |  |   template<class charT> class basic_format_parse_context; | 
					
						
							|  |  |  |   using format_parse_context = basic_format_parse_context<char>; | 
					
						
							|  |  |  |   using wformat_parse_context = basic_format_parse_context<wchar_t>; | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |    | 
					
						
							|  |  |  |   template<class Out, class charT> class basic_format_context; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   using format_context = basic_format_context< | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |     /* unspecified */ std::back_insert_iterator<fmt::internal::buffer<char>>, char>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   using wformat_context = basic_format_context< | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |     /* unspecified */ std::back_insert_iterator<fmt::internal::buffer<wchar_t>>, wchar_t>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   template<class T, class charT = char> struct formatter { | 
					
						
							|  |  |  |     formatter() = delete; | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   // [format.arguments], arguments | 
					
						
							|  |  |  |   template<class Context> class basic_format_arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<class Visitor, class Context> | 
					
						
							|  |  |  |     /* see below */ auto visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<class Context, class... Args> struct format_arg_store; // exposition only | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<class Context> class basic_format_args; | 
					
						
							|  |  |  |   using format_args = basic_format_args<format_context>; | 
					
						
							|  |  |  |   using wformat_args = basic_format_args<wformat_context>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |   template<class Out, class charT> | 
					
						
							|  |  |  |     using format_args_t = basic_format_args<basic_format_context<Out, charT>>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   template<class Context = format_context, class... Args> | 
					
						
							|  |  |  |     format_arg_store<Context, Args...> | 
					
						
							|  |  |  |       make_format_args(const Args&... args); | 
					
						
							|  |  |  |   template<class... Args> | 
					
						
							|  |  |  |     format_arg_store<wformat_context, Args...> | 
					
						
							|  |  |  |       make_wformat_args(const Args&... args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // [format.functions], formatting functions | 
					
						
							|  |  |  |   template<class... Args> | 
					
						
							|  |  |  |     string format(string_view fmt, const Args&... args); | 
					
						
							|  |  |  |   template<class... Args> | 
					
						
							|  |  |  |     wstring format(wstring_view fmt, const Args&... args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   string vformat(string_view fmt, format_args args); | 
					
						
							|  |  |  |   wstring vformat(wstring_view fmt, wformat_args args); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |   template<class Out, class... Args> | 
					
						
							|  |  |  |     Out format_to(Out out, string_view fmt, const Args&... args); | 
					
						
							|  |  |  |   template<class Out, class... Args> | 
					
						
							|  |  |  |     Out format_to(Out out, wstring_view fmt, const Args&... args); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |   template<class Out> | 
					
						
							|  |  |  |     Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args); | 
					
						
							|  |  |  |   template<class Out> | 
					
						
							|  |  |  |     Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |   template<class Out> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     struct format_to_n_result { | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |       Out out; | 
					
						
							|  |  |  |       iter_difference_t<Out> size; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |    | 
					
						
							|  |  |  |   template<class Out, class... Args> | 
					
						
							|  |  |  |     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, | 
					
						
							|  |  |  |                                         string_view fmt, const Args&... args); | 
					
						
							|  |  |  |   template<class Out, class... Args> | 
					
						
							|  |  |  |     format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, | 
					
						
							|  |  |  |                                         wstring_view fmt, const Args&... args); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   template<class... Args> | 
					
						
							|  |  |  |     size_t formatted_size(string_view fmt, const Args&... args); | 
					
						
							|  |  |  |   template<class... Args> | 
					
						
							|  |  |  |     size_t formatted_size(wstring_view fmt, const Args&... args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.error | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   class format_error : public runtime_error { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     explicit format_error(const string& what_arg) : runtime_error(what_arg) {} | 
					
						
							|  |  |  |     explicit format_error(const char* what_arg) : runtime_error(what_arg) {} | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-13 07:30:55 -07:00
										 |  |  | namespace std { | 
					
						
							|  |  |  | namespace detail { | 
					
						
							|  |  |  | struct error_handler { | 
					
						
							|  |  |  |   // This function is intentionally not constexpr to give a compile-time error. | 
					
						
							|  |  |  |   void on_error(const char* message) { | 
					
						
							|  |  |  |     throw std::format_error(message); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.parse_context | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   template<class charT> | 
					
						
							|  |  |  |   class basic_format_parse_context { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     using char_type = charT; | 
					
						
							|  |  |  |     using const_iterator = typename basic_string_view<charT>::const_iterator; | 
					
						
							|  |  |  |     using iterator = const_iterator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							|  |  |  |     iterator begin_;                              // exposition only | 
					
						
							|  |  |  |     iterator end_;                                // exposition only | 
					
						
							|  |  |  |     enum indexing { unknown, manual, automatic }; // exposition only | 
					
						
							|  |  |  |     indexing indexing_;                           // exposition only | 
					
						
							|  |  |  |     size_t next_arg_id_;                          // exposition only | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     size_t num_args_;                             // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public: | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     explicit constexpr basic_format_parse_context(basic_string_view<charT> fmt, | 
					
						
							|  |  |  |                                                   size_t num_args = 0) noexcept; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     basic_format_parse_context(const basic_format_parse_context&) = delete; | 
					
						
							|  |  |  |     basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constexpr const_iterator begin() const noexcept; | 
					
						
							|  |  |  |     constexpr const_iterator end() const noexcept; | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     constexpr void advance_to(const_iterator it); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constexpr size_t next_arg_id(); | 
					
						
							|  |  |  |     constexpr void check_arg_id(size_t id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Implementation detail: | 
					
						
							|  |  |  |     constexpr void check_arg_id(fmt::string_view) {} | 
					
						
							| 
									
										
										
										
											2019-04-13 07:30:55 -07:00
										 |  |  |     detail::error_handler error_handler() const { return {}; } | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     void on_error(const char* msg) { error_handler().on_error(msg); } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | template<class charT> | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  | /* explicit */ constexpr basic_format_parse_context<charT>:: | 
					
						
							|  |  |  |                    basic_format_parse_context(basic_string_view<charT> fmt, | 
					
						
							|  |  |  |                                               size_t num_args) noexcept | 
					
						
							|  |  |  | : begin_(fmt.begin()), end_(fmt.end()), indexing_(unknown), next_arg_id_(0), num_args_(num_args) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<class charT> | 
					
						
							|  |  |  | constexpr typename basic_format_parse_context<charT>::const_iterator basic_format_parse_context<charT>::begin() const noexcept { return begin_; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class charT> | 
					
						
							|  |  |  | constexpr typename basic_format_parse_context<charT>::const_iterator basic_format_parse_context<charT>::end() const noexcept { return end_; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class charT> | 
					
						
							|  |  |  | constexpr void basic_format_parse_context<charT>::advance_to(typename basic_format_parse_context<charT>::iterator it) { begin_ = it; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class charT> | 
					
						
							|  |  |  | constexpr size_t basic_format_parse_context<charT>::next_arg_id() { | 
					
						
							|  |  |  |   if (indexing_ == manual) | 
					
						
							|  |  |  |     throw format_error("manual to automatic indexing"); | 
					
						
							|  |  |  |   if (indexing_ == unknown) | 
					
						
							|  |  |  |     indexing_ = automatic; | 
					
						
							|  |  |  |   return next_arg_id_++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class charT> | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  | constexpr void basic_format_parse_context<charT>::check_arg_id(size_t id) { | 
					
						
							|  |  |  |   // clang doesn't support __builtin_is_constant_evaluated yet | 
					
						
							|  |  |  |   //if (!(!__builtin_is_constant_evaluated() || id < num_args_)) | 
					
						
							|  |  |  |   //  throw format_error(invalid index is out of range"); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   if (indexing_ == automatic) | 
					
						
							|  |  |  |     throw format_error("automatic to manual indexing"); | 
					
						
							|  |  |  |   if (indexing_ == unknown) | 
					
						
							|  |  |  |     indexing_ = manual; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.context | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |   template<class Out, class charT> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   class basic_format_context { | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |     basic_format_args<basic_format_context> args_; // exposition only | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     Out out_;                                      // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   public: | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     using iterator = Out; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     using char_type = charT; | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     template<class T> using formatter_type = formatter<T, charT>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     basic_format_arg<basic_format_context> arg(size_t id) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iterator out(); | 
					
						
							|  |  |  |     void advance_to(iterator it); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Implementation details: | 
					
						
							|  |  |  |     using format_arg = basic_format_arg<basic_format_context>; | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref) | 
					
						
							| 
									
										
										
										
											2019-02-23 14:40:08 -05:00
										 |  |  |     : args_(args), out_(out) {} | 
					
						
							| 
									
										
										
										
											2019-04-13 07:30:55 -07:00
										 |  |  |     detail::error_handler error_handler() const { return {}; } | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const { | 
					
						
							|  |  |  |       return {}; // unused: named arguments are not supported yet | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void on_error(const char* msg) { error_handler().on_error(msg); } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | template<class O, class charT> | 
					
						
							|  |  |  | basic_format_arg<basic_format_context<O, charT>> basic_format_context<O, charT>::arg(size_t id) const { return args_.get(id); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class O, class charT> | 
					
						
							|  |  |  | typename basic_format_context<O, charT>::iterator basic_format_context<O, charT>::out() { return out_; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class O, class charT> | 
					
						
							|  |  |  | void basic_format_context<O, charT>::advance_to(typename basic_format_context<O, charT>::iterator it) { out_ = it; } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  | namespace std { | 
					
						
							|  |  |  | namespace detail { | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | constexpr bool is_standard_integer_v = | 
					
						
							|  |  |  |     std::is_same_v<T, signed char> || | 
					
						
							|  |  |  |     std::is_same_v<T, short int> || | 
					
						
							|  |  |  |     std::is_same_v<T, int> || | 
					
						
							|  |  |  |     std::is_same_v<T, long int> || | 
					
						
							|  |  |  |     std::is_same_v<T, long long int>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | constexpr bool is_standard_unsigned_integer_v = | 
					
						
							|  |  |  |     std::is_same_v<T, unsigned char> || | 
					
						
							|  |  |  |     std::is_same_v<T, unsigned short int> || | 
					
						
							|  |  |  |     std::is_same_v<T, unsigned int> || | 
					
						
							|  |  |  |     std::is_same_v<T, unsigned long int> || | 
					
						
							|  |  |  |     std::is_same_v<T, unsigned long long int>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  | template <typename T, typename Char> struct formatter; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.arg | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   template<class Context> | 
					
						
							|  |  |  |   class basic_format_arg { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     class handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |   private: | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     using char_type = typename Context::char_type;                       // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     variant<monostate, bool, char_type, | 
					
						
							|  |  |  |             int, unsigned int, long long int, unsigned long long int, | 
					
						
							|  |  |  |             double, long double, | 
					
						
							|  |  |  |             const char_type*, basic_string_view<char_type>, | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |             const void*, handle> value;                                  // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     template<typename T, | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |       typename = enable_if_t< | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |         std::is_same_v<T, bool> || | 
					
						
							|  |  |  |         std::is_same_v<T, char_type> || | 
					
						
							|  |  |  |         (std::is_same_v<T, char> && std::is_same_v<char_type, wchar_t>) || | 
					
						
							|  |  |  |         detail::is_standard_integer_v<T> || | 
					
						
							|  |  |  |         detail::is_standard_unsigned_integer_v<T> || | 
					
						
							|  |  |  |         is_default_constructible_v<typename Context::template formatter_type<T>> | 
					
						
							|  |  |  |     >> explicit basic_format_arg(const T& v) noexcept; // exposition only | 
					
						
							|  |  |  |     explicit basic_format_arg(float n) noexcept;                         // exposition only | 
					
						
							|  |  |  |     explicit basic_format_arg(double n) noexcept;                        // exposition only | 
					
						
							|  |  |  |     explicit basic_format_arg(long double n) noexcept;                   // exposition only | 
					
						
							|  |  |  |     explicit basic_format_arg(const char_type* s);                       // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     template<class traits> | 
					
						
							|  |  |  |       explicit basic_format_arg( | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |         basic_string_view<char_type, traits> s) noexcept;                // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     template<class traits, class Allocator> | 
					
						
							|  |  |  |       explicit basic_format_arg( | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |         const basic_string<char_type, traits, Allocator>& s) noexcept;   // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     explicit basic_format_arg(nullptr_t) noexcept;                       // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     template<class T, typename = enable_if_t<is_void_v<T>>> | 
					
						
							|  |  |  |       explicit basic_format_arg(const T* p) noexcept;                    // exposition only | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     // Fails due to a bug in clang | 
					
						
							|  |  |  |     //template<class Visitor, class Ctx> | 
					
						
							|  |  |  |     //  friend auto visit_format_arg(Visitor&& vis, | 
					
						
							|  |  |  |     //                                    basic_format_arg<Ctx> arg);           // exposition only | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     friend auto get_value(basic_format_arg arg) { | 
					
						
							|  |  |  |       return arg.value; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  |     template <typename T, typename Char> friend struct detail::formatter; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     template<class Ctx, class... Args> | 
					
						
							|  |  |  |       friend format_arg_store<Ctx, Args...> | 
					
						
							|  |  |  |         make_format_args(const Args&... args);                           // exposition only | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |   public: | 
					
						
							|  |  |  |     basic_format_arg() noexcept; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     explicit operator bool() const noexcept; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | basic_format_arg<Context>::basic_format_arg() noexcept {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  | template<class T, typename> /* explicit */ basic_format_arg<Context>::basic_format_arg(const T& v) noexcept { | 
					
						
							|  |  |  |   if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, char_type>) | 
					
						
							|  |  |  |     value = v; | 
					
						
							|  |  |  |   else if constexpr (std::is_same_v<T, char> && std::is_same_v<char_type, wchar_t>) | 
					
						
							|  |  |  |     value = static_cast<wchar_t>(v); | 
					
						
							|  |  |  |   else if constexpr (detail::is_standard_integer_v<T> && sizeof(T) <= sizeof(int)) | 
					
						
							|  |  |  |     value = static_cast<int>(v); | 
					
						
							|  |  |  |   else if constexpr (detail::is_standard_unsigned_integer_v<T> && sizeof(T) <= sizeof(unsigned)) | 
					
						
							|  |  |  |     value = static_cast<unsigned>(v); | 
					
						
							|  |  |  |   else if constexpr (detail::is_standard_integer_v<T>) | 
					
						
							|  |  |  |     value = static_cast<long long int>(v); | 
					
						
							|  |  |  |   else if constexpr (detail::is_standard_unsigned_integer_v<T>) | 
					
						
							|  |  |  |     value = static_cast<unsigned long long int>(v); | 
					
						
							|  |  |  |   else if constexpr (is_default_constructible_v<typename Context::template formatter_type<T>>) | 
					
						
							|  |  |  |     value = handle(v); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(float n) noexcept | 
					
						
							|  |  |  |   : value(static_cast<double>(n)) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(double n) noexcept | 
					
						
							|  |  |  |   : value(n) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(long double n) noexcept | 
					
						
							|  |  |  |   : value(n) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(const typename basic_format_arg<Context>::char_type* s) | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   : value(s) { | 
					
						
							|  |  |  |   assert(s != nullptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | template<class traits> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(basic_string_view<char_type, traits> s) noexcept | 
					
						
							|  |  |  |   : value(s) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | template<class traits, class Allocator> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg( | 
					
						
							|  |  |  |     const basic_string<char_type, traits, Allocator>& s) noexcept | 
					
						
							|  |  |  |   : value(basic_string_view<char_type>(s.data(), s.size())) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::basic_format_arg(nullptr_t) noexcept | 
					
						
							|  |  |  |   : value(static_cast<const void*>(nullptr)) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | template<class T, typename> /* explicit */ basic_format_arg<Context>::basic_format_arg(const T* p) noexcept | 
					
						
							|  |  |  |   : value(p) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  | template<class Context> | 
					
						
							|  |  |  | /* explicit */ basic_format_arg<Context>::operator bool() const noexcept { | 
					
						
							|  |  |  |     return !holds_alternative<monostate>(value); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  |   template<class Context> | 
					
						
							|  |  |  |   class basic_format_arg<Context>::handle { | 
					
						
							|  |  |  |     const void* ptr_;                                         // exposition only | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |     void (*format_)(basic_format_parse_context<char_type>&, | 
					
						
							|  |  |  |                     Context&, const void*);                   // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |     template<class T> explicit handle(const T& val) noexcept; // exposition only | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     friend class basic_format_arg<Context>;                   // exposition only | 
					
						
							| 
									
										
										
										
											2019-04-10 07:45:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 06:25:42 -07:00
										 |  |  |   public: | 
					
						
							|  |  |  |     void format(basic_format_parse_context<char_type>&, Context& ctx) const; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | template<class T> /* explicit */ basic_format_arg<Context>::handle::handle(const T& val) noexcept | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   : ptr_(&val), format_([](basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx, const void* ptr) { | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     typename Context::template formatter_type<T> f; | 
					
						
							|  |  |  |     parse_ctx.advance_to(f.parse(parse_ctx)); | 
					
						
							|  |  |  |     format_ctx.advance_to(f.format(*static_cast<const T*>(ptr), format_ctx)); | 
					
						
							|  |  |  |   }) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  | void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const { | 
					
						
							|  |  |  |   format_(parse_ctx, format_ctx, ptr_); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.visit | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | template<class Visitor, class Context> | 
					
						
							|  |  |  |   auto visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg) { | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     return visit(vis, get_value(arg)); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.store | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   template<class Context, class... Args> | 
					
						
							|  |  |  |   struct format_arg_store { // exposition only | 
					
						
							|  |  |  |     array<basic_format_arg<Context>, sizeof...(Args)> args; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.basic_args | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | namespace std { | 
					
						
							|  |  |  |   template<class Context> | 
					
						
							|  |  |  |   class basic_format_args { | 
					
						
							|  |  |  |     size_t size_;                           // exposition only | 
					
						
							|  |  |  |     const basic_format_arg<Context>* data_; // exposition only | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     basic_format_args() noexcept; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     template<class... Args> | 
					
						
							|  |  |  |       basic_format_args(const format_arg_store<Context, Args...>& store) noexcept; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     basic_format_arg<Context> get(size_t i) const noexcept; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | basic_format_args<Context>::basic_format_args() noexcept : size_(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | template<class... Args> | 
					
						
							|  |  |  |   basic_format_args<Context>::basic_format_args(const format_arg_store<Context, Args...>& store) noexcept | 
					
						
							|  |  |  |   : size_(sizeof...(Args)), data_(store.args.data()) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class Context> | 
					
						
							|  |  |  | basic_format_arg<Context> basic_format_args<Context>::get(size_t i) const noexcept { | 
					
						
							|  |  |  |   return i < size_ ? data_[i] : basic_format_arg<Context>(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.make_args | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | template<class Context /*= format_context*/, class... Args> | 
					
						
							|  |  |  |   format_arg_store<Context, Args...> make_format_args(const Args&... args) { | 
					
						
							|  |  |  |     return {basic_format_arg<Context>(args)...}; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.make_wargs | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | template<class... Args> | 
					
						
							|  |  |  |   format_arg_store<wformat_context, Args...> make_wformat_args(const Args&... args) { | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     return make_format_args<wformat_context>(args...); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace std { | 
					
						
							|  |  |  | namespace detail { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Range> | 
					
						
							|  |  |  | class arg_formatter | 
					
						
							| 
									
										
										
										
											2019-06-13 20:16:06 -07:00
										 |  |  |     : public fmt::internal::arg_formatter_base<Range, error_handler> { | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   using char_type = typename Range::value_type; | 
					
						
							| 
									
										
										
										
											2019-04-13 07:30:55 -07:00
										 |  |  |   using base = fmt::internal::arg_formatter_base<Range, error_handler>; | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   using format_context = std::basic_format_context<typename base::iterator, char_type>; | 
					
						
							|  |  |  |   using parse_context = basic_format_parse_context<char_type>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 06:48:25 -07:00
										 |  |  |   parse_context* parse_ctx_; | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   format_context& ctx_; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   typedef Range range; | 
					
						
							|  |  |  |   typedef typename base::iterator iterator; | 
					
						
							|  |  |  |   typedef typename base::format_specs format_specs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |     \rst | 
					
						
							|  |  |  |     Constructs an argument formatter object. | 
					
						
							|  |  |  |     *ctx* is a reference to the formatting context, | 
					
						
							|  |  |  |     *spec* contains format specifier information for standard argument types. | 
					
						
							|  |  |  |     \endrst | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-05-30 07:01:31 -07:00
										 |  |  |   arg_formatter(format_context& ctx, parse_context* parse_ctx = nullptr, fmt::format_specs* spec = nullptr) | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |       : base(Range(ctx.out()), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   using base::operator(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** Formats an argument of a user-defined type. */ | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   iterator operator()(typename std::basic_format_arg<format_context>::handle handle) { | 
					
						
							| 
									
										
										
										
											2019-03-20 06:48:25 -07:00
										 |  |  |     handle.format(*parse_ctx_, ctx_); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     return this->out(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   iterator operator()(monostate) { | 
					
						
							|  |  |  |     throw format_error(""); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Context> | 
					
						
							|  |  |  | inline fmt::internal::type get_type(basic_format_arg<Context> arg) { | 
					
						
							|  |  |  |   return visit_format_arg([&] (auto val) { | 
					
						
							|  |  |  |     using char_type = typename Context::char_type; | 
					
						
							|  |  |  |     using T = decltype(val); | 
					
						
							|  |  |  |     if (std::is_same_v<T, monostate>) | 
					
						
							|  |  |  |       return fmt::internal::none_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, bool>) | 
					
						
							|  |  |  |       return fmt::internal::bool_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, char_type>) | 
					
						
							|  |  |  |       return fmt::internal::char_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, int>) | 
					
						
							|  |  |  |       return fmt::internal::int_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, unsigned int>) | 
					
						
							|  |  |  |       return fmt::internal::uint_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, long long int>) | 
					
						
							|  |  |  |       return fmt::internal::long_long_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, unsigned long long int>) | 
					
						
							|  |  |  |       return fmt::internal::ulong_long_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, double>) | 
					
						
							|  |  |  |       return fmt::internal::double_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, long double>) | 
					
						
							|  |  |  |       return fmt::internal::long_double_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, const char_type*>) | 
					
						
							|  |  |  |       return fmt::internal::cstring_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, basic_string_view<char_type>>) | 
					
						
							|  |  |  |       return fmt::internal::string_type; | 
					
						
							|  |  |  |     if (std::is_same_v<T, const void*>) | 
					
						
							|  |  |  |       return fmt::internal::pointer_type; | 
					
						
							| 
									
										
										
										
											2019-04-10 09:02:24 -07:00
										 |  |  |     assert(get_value(arg).index() == 12); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     return fmt::internal::custom_type; | 
					
						
							|  |  |  |   }, arg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  | template <typename Context> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | class custom_formatter { | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   using parse_context = basic_format_parse_context<typename Context::char_type>; | 
					
						
							|  |  |  |   parse_context& parse_ctx_; | 
					
						
							|  |  |  |   Context& format_ctx_; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   custom_formatter(parse_context& parse_ctx, Context& ctx) : parse_ctx_(parse_ctx), format_ctx_(ctx) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   bool operator()(typename basic_format_arg<Context>::handle h) const { | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |     h.format(parse_ctx_, format_ctx_); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template <typename T> bool operator()(T) const { return false; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename ArgFormatter, typename Char, typename Context> | 
					
						
							| 
									
										
										
										
											2019-04-13 07:30:55 -07:00
										 |  |  | struct format_handler : detail::error_handler { | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   typedef typename ArgFormatter::range range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   format_handler(range r, basic_string_view<Char> str, | 
					
						
							|  |  |  |                  basic_format_args<Context> format_args, | 
					
						
							|  |  |  |                  fmt::internal::locale_ref loc) | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |       : parse_ctx(str), context(r.begin(), format_args, loc) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void on_text(const Char* begin, const Char* end) { | 
					
						
							|  |  |  |     auto size = fmt::internal::to_unsigned(end - begin); | 
					
						
							|  |  |  |     auto out = context.out(); | 
					
						
							|  |  |  |     auto&& it = fmt::internal::reserve(out, size); | 
					
						
							|  |  |  |     it = std::copy_n(begin, size, it); | 
					
						
							|  |  |  |     context.advance_to(out); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   void on_arg_id() { | 
					
						
							|  |  |  |     arg = context.arg(parse_ctx.next_arg_id()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   void on_arg_id(unsigned id) { | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |     parse_ctx.check_arg_id(id); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     arg = context.arg(id); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-02-23 14:40:08 -05:00
										 |  |  |   void on_arg_id(fmt::basic_string_view<Char>) {} | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void on_replacement_field(const Char* p) { | 
					
						
							| 
									
										
										
										
											2019-05-14 22:41:11 +07:00
										 |  |  |     parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin())); | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |     custom_formatter<Context> f(parse_ctx, context); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     if (!visit_format_arg(f, arg)) | 
					
						
							| 
									
										
										
										
											2019-03-20 06:48:25 -07:00
										 |  |  |       context.advance_to(visit_format_arg(ArgFormatter(context, &parse_ctx), arg)); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const Char* on_format_specs(const Char* begin, const Char* end) { | 
					
						
							| 
									
										
										
										
											2019-05-14 22:41:11 +07:00
										 |  |  |     parse_ctx.advance_to(parse_ctx.begin() + (begin - &*parse_ctx.begin())); | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |     custom_formatter<Context> f(parse_ctx, context); | 
					
						
							| 
									
										
										
										
											2019-05-14 22:41:11 +07:00
										 |  |  |     if (visit_format_arg(f, arg)) return &*parse_ctx.begin(); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     fmt::basic_format_specs<Char> specs; | 
					
						
							|  |  |  |     using fmt::internal::specs_handler; | 
					
						
							| 
									
										
										
										
											2019-02-09 16:15:20 -08:00
										 |  |  |     using parse_context = basic_format_parse_context<Char>; | 
					
						
							|  |  |  |     fmt::internal::specs_checker<specs_handler<parse_context, Context>> handler( | 
					
						
							|  |  |  |         specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg)); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     begin = parse_format_specs(begin, end, handler); | 
					
						
							|  |  |  |     if (begin == end || *begin != '}') on_error("missing '}' in format string"); | 
					
						
							| 
									
										
										
										
											2019-05-14 22:41:11 +07:00
										 |  |  |     parse_ctx.advance_to(parse_ctx.begin() + (begin - &*parse_ctx.begin())); | 
					
						
							| 
									
										
										
										
											2019-03-20 06:48:25 -07:00
										 |  |  |     context.advance_to(visit_format_arg(ArgFormatter(context, &parse_ctx, &specs), arg)); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     return begin; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-10 06:34:47 -08:00
										 |  |  |   basic_format_parse_context<Char> parse_ctx; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   Context context; | 
					
						
							|  |  |  |   basic_format_arg<Context> arg; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T, typename Char> | 
					
						
							|  |  |  | struct formatter { | 
					
						
							|  |  |  |   // Parses format specifiers stopping either at the end of the range or at the | 
					
						
							|  |  |  |   // terminating '}'. | 
					
						
							|  |  |  |   template <typename ParseContext> | 
					
						
							|  |  |  |   FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) { | 
					
						
							|  |  |  |     namespace internal = fmt::internal; | 
					
						
							|  |  |  |     typedef internal::dynamic_specs_handler<ParseContext> handler_type; | 
					
						
							| 
									
										
										
										
											2019-06-10 21:21:45 -07:00
										 |  |  |     auto type = internal::mapped_type_constant<T, fmt::buffer_context<Char>>::value; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     internal::specs_checker<handler_type> handler(handler_type(specs_, ctx), | 
					
						
							|  |  |  |                                                   type); | 
					
						
							|  |  |  |     auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); | 
					
						
							|  |  |  |     auto type_spec = specs_.type; | 
					
						
							|  |  |  |     auto eh = ctx.error_handler(); | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |     case internal::none_type: | 
					
						
							|  |  |  |     case internal::named_arg_type: | 
					
						
							|  |  |  |       FMT_ASSERT(false, "invalid argument type"); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::int_type: | 
					
						
							|  |  |  |     case internal::uint_type: | 
					
						
							|  |  |  |     case internal::long_long_type: | 
					
						
							|  |  |  |     case internal::ulong_long_type: | 
					
						
							|  |  |  |     case internal::bool_type: | 
					
						
							|  |  |  |       handle_int_type_spec(type_spec, | 
					
						
							|  |  |  |                            internal::int_type_checker<decltype(eh)>(eh)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::char_type: | 
					
						
							|  |  |  |       handle_char_specs( | 
					
						
							|  |  |  |           &specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::double_type: | 
					
						
							|  |  |  |     case internal::long_double_type: | 
					
						
							|  |  |  |       handle_float_type_spec(type_spec, | 
					
						
							|  |  |  |                              internal::float_type_checker<decltype(eh)>(eh)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::cstring_type: | 
					
						
							|  |  |  |       internal::handle_cstring_type_spec( | 
					
						
							|  |  |  |           type_spec, internal::cstring_type_checker<decltype(eh)>(eh)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::string_type: | 
					
						
							|  |  |  |       internal::check_string_type_spec(type_spec, eh); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::pointer_type: | 
					
						
							|  |  |  |       internal::check_pointer_type_spec(type_spec, eh); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case internal::custom_type: | 
					
						
							|  |  |  |       // Custom format specifiers should be checked in parse functions of | 
					
						
							|  |  |  |       // formatter specializations. | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return it; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template <typename FormatContext> | 
					
						
							|  |  |  |   auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>( | 
					
						
							| 
									
										
										
										
											2019-05-30 07:01:31 -07:00
										 |  |  |         specs_.width_, specs_.width_ref, ctx, nullptr); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>( | 
					
						
							| 
									
										
										
										
											2019-05-30 07:01:31 -07:00
										 |  |  |         specs_.precision, specs_.precision_ref, ctx, nullptr); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |     typedef fmt::output_range<typename FormatContext::iterator, | 
					
						
							|  |  |  |                          typename FormatContext::char_type> | 
					
						
							|  |  |  |         range_type; | 
					
						
							| 
									
										
										
										
											2019-05-30 07:01:31 -07:00
										 |  |  |     return visit_format_arg(arg_formatter<range_type>(ctx, nullptr, &specs_), | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |                             basic_format_arg<FormatContext>(val)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   fmt::internal::dynamic_format_specs<Char> specs_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | }  // namespace detail | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 15:42:00 -07:00
										 |  |  | // https://fmt.dev/Text%20Formatting.html#format.functions | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | template<class... Args> | 
					
						
							|  |  |  |   string format(string_view fmt, const Args&... args) { | 
					
						
							|  |  |  |     return vformat(fmt, make_format_args(args...)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class... Args> | 
					
						
							|  |  |  |   wstring format(wstring_view fmt, const Args&... args) { | 
					
						
							|  |  |  |     return vformat(fmt, make_wformat_args(args...)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | string vformat(string_view fmt, format_args args) { | 
					
						
							|  |  |  |   fmt::memory_buffer mbuf; | 
					
						
							| 
									
										
										
										
											2019-04-07 10:05:49 -07:00
										 |  |  |   fmt::internal::buffer<char>& buf = mbuf; | 
					
						
							| 
									
										
										
										
											2019-06-19 13:51:36 -07:00
										 |  |  |   using range = fmt::internal::buffer_range<char>; | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   detail::format_handler<detail::arg_formatter<range>, char, format_context> | 
					
						
							|  |  |  |     h(range(std::back_inserter(buf)), fmt, args, {}); | 
					
						
							|  |  |  |   fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h); | 
					
						
							|  |  |  |   return to_string(mbuf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wstring vformat(wstring_view fmt, wformat_args args); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  | template<class Out, class... Args> | 
					
						
							|  |  |  |   Out format_to(Out out, string_view fmt, const Args&... args) { | 
					
						
							|  |  |  |     using context = basic_format_context<Out, decltype(fmt)::value_type>; | 
					
						
							|  |  |  |     return vformat_to(out, fmt, {make_format_args<context>(args...)}); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  | template<class Out, class... Args> | 
					
						
							|  |  |  |   Out format_to(Out out, wstring_view fmt, const Args&... args) { | 
					
						
							|  |  |  |     using context = basic_format_context<Out, decltype(fmt)::value_type>; | 
					
						
							|  |  |  |     return vformat_to(out, fmt, {make_format_args<context>(args...)}); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  | template<class Out> | 
					
						
							|  |  |  |   Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args) { | 
					
						
							|  |  |  |     typedef fmt::output_range<Out, char> range; | 
					
						
							|  |  |  |     detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<Out, char>> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |       h(range(out), fmt, args, {}); | 
					
						
							|  |  |  |     fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h); | 
					
						
							|  |  |  |     return h.context.out(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  | template<class Out> | 
					
						
							|  |  |  |   Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  | template<class Out, class... Args> | 
					
						
							|  |  |  |   format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, | 
					
						
							|  |  |  |                                       string_view fmt, const Args&... args); | 
					
						
							|  |  |  | template<class Out, class... Args> | 
					
						
							|  |  |  |   format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, | 
					
						
							|  |  |  |                                       wstring_view fmt, const Args&... args); | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<class... Args> | 
					
						
							|  |  |  |   size_t formatted_size(string_view fmt, const Args&... args); | 
					
						
							|  |  |  | template<class... Args> | 
					
						
							|  |  |  |   size_t formatted_size(wstring_view fmt, const Args&... args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define charT char | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<charT, charT> : detail::formatter<charT, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<char, wchar_t>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<charT*, charT> : detail::formatter<const charT*, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<const charT*, charT> : detail::formatter<const charT*, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<size_t N> struct formatter<const charT[N], charT> | 
					
						
							|  |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class traits, class Allocator> | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  |   struct formatter<basic_string<charT, traits, Allocator>, charT> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class traits> | 
					
						
							| 
									
										
										
										
											2019-04-10 08:29:07 -07:00
										 |  |  |   struct formatter<basic_string_view<charT, traits>, charT> | 
					
						
							| 
									
										
										
										
											2019-01-19 09:10:57 -08:00
										 |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<nullptr_t, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<void*, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<const void*, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<bool, charT> : detail::formatter<bool, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<signed char, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<short, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<int, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::conditional_t<sizeof(long) == sizeof(int), int, long long>, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long long, charT> : detail::formatter<long long, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned char, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned short, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned int, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned long, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::conditional_t<sizeof(long) == sizeof(int), unsigned, unsigned long long>, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned long long, charT> : detail::formatter<unsigned long long, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<float, charT> : detail::formatter<double, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<double, charT> : detail::formatter<double, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long double, charT> : detail::formatter<long double, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef charT | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define charT wchar_t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<charT, charT> : detail::formatter<charT, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<char, wchar_t> : detail::formatter<charT, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<charT*, charT> : detail::formatter<const charT*, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<> struct formatter<const charT*, charT> : detail::formatter<const charT*, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<size_t N> struct formatter<const charT[N], charT> | 
					
						
							|  |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class traits, class Allocator> | 
					
						
							|  |  |  |   struct formatter<std::basic_string<charT, traits, Allocator>, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class traits> | 
					
						
							|  |  |  |   struct formatter<std::basic_string_view<charT, traits>, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::basic_string_view<charT>, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<nullptr_t, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<void*, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<const void*, charT> : detail::formatter<const void*, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<bool, charT> : detail::formatter<bool, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<signed char, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<short, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<int, charT> : detail::formatter<int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::conditional_t<sizeof(long) == sizeof(int), int, long long>, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long long, charT> : detail::formatter<long long, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned char, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned short, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned int, charT> : detail::formatter<unsigned int, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned long, charT> | 
					
						
							|  |  |  |       : detail::formatter<std::conditional_t<sizeof(long) == sizeof(int), unsigned, unsigned long long>, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<unsigned long long, charT> : detail::formatter<unsigned long long, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<float, charT> : detail::formatter<double, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<double, charT> : detail::formatter<double, charT> {}; | 
					
						
							|  |  |  | template <> struct formatter<long double, charT> : detail::formatter<long double, charT> {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef charT | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<> struct formatter<const wchar_t, char> { | 
					
						
							|  |  |  |     formatter() = delete; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif  // FMT_FORMAT_ |