11 #include <initializer_list>
13 #include <type_traits>
21 template <
typename Range,
typename OutputIt>
22 auto copy(
const Range& range, OutputIt out) -> OutputIt {
23 for (
auto it = range.begin(), end = range.end(); it != end; ++it)
28 template <
typename OutputIt>
29 auto copy(
const char* str, OutputIt out) -> OutputIt {
30 while (*str) *out++ = *str++;
34 template <
typename OutputIt>
auto copy(
char ch, OutputIt out) -> OutputIt {
39 template <
typename OutputIt>
auto copy(
wchar_t ch, OutputIt out) -> OutputIt {
47 static auto check(U* p)
48 -> decltype((
void)p->find(
'a'), p->length(), (
void)p->data(),
int());
49 template <
typename>
static void check(...);
52 static constexpr
const bool value =
54 std::is_convertible<T, std_string_view<char>>
::value ||
55 !std::is_void<decltype(check<T>(
nullptr))>::
value;
58 template <
typename Char>
62 template <
typename U>
static auto check(U*) ->
typename U::mapped_type;
63 template <
typename>
static void check(...);
66 #ifdef FMT_FORMAT_MAP_AS_LIST // DEPRECATED!
67 static constexpr
const bool value =
false;
69 static constexpr
const bool value =
70 !std::is_void<decltype(check<T>(
nullptr))>::
value;
75 template <
typename U>
static auto check(U*) ->
typename U::key_type;
76 template <
typename>
static void check(...);
79 #ifdef FMT_FORMAT_SET_AS_LIST // DEPRECATED!
80 static constexpr
const bool value =
false;
82 static constexpr
const bool value =
91 #if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
93 # define FMT_DECLTYPE_RETURN(val) \
94 ->decltype(val) { return val; } \
96 true, "") // This makes it so that a semicolon is required after the
100 template <
typename T, std::
size_t N>
104 template <
typename T, std::
size_t N>
109 template <
typename T,
typename Enable =
void>
112 template <
typename T>
114 decltype(std::declval<T>().end())>>
118 template <
typename T>
120 template <
typename T>
125 template <
typename T>
128 decltype(begin(
static_cast<T&&
>(rng)))> {
129 return begin(
static_cast<T&&
>(rng));
131 template <
typename T>
133 decltype(end(
static_cast<T&&
>(rng)))> {
134 return end(
static_cast<T&&
>(rng));
137 template <
typename T,
typename Enable =
void>
139 template <
typename T,
typename Enable =
void>
142 template <
typename T>
147 decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
150 template <
typename T>
153 decltype(detail::range_end(std::declval<T>())),
158 template <
typename T>
160 : std::integral_constant<bool, (has_const_begin_end<T>::value ||
161 has_mutable_begin_end<T>::value)> {};
162 # undef FMT_DECLTYPE_RETURN
167 template <
typename U>
168 static auto check(U* p) -> decltype(std::tuple_size<U>::value,
int());
169 template <
typename>
static void check(...);
173 !std::is_void<decltype(check<T>(
nullptr))>::
value;
177 #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
178 template <
typename T, T... N>
191 template <
typename T,
size_t N, T... Ns>
193 template <
typename T, T... Ns>
200 template <
typename T>
203 template <typename T, typename C, bool = is_tuple_like_<T>::value>
206 static constexpr
const bool value =
false;
225 template <
typename Tuple,
typename F,
size_t... Is>
229 const int unused[] = {0, ((
void)
f(get<Is>(t)), 0)...};
233 template <
typename Tuple,
typename F>
236 std::forward<Tuple>(t), std::forward<F>(
f));
239 template <
typename Tuple1,
typename Tuple2,
typename F,
size_t... Is>
242 const int unused[] = {0, ((
void)
f(get<Is>(t1), get<Is>(t2)), 0)...};
246 template <
typename Tuple1,
typename Tuple2,
typename F>
249 std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
255 template <
typename Char,
typename... T>
256 using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
259 template <
typename Tuple,
typename Char,
std::size_t... Is>
264 #if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
266 template <
typename R>
struct range_reference_type_impl {
270 template <
typename T, std::
size_t N>
struct range_reference_type_impl<T[N]> {
274 template <
typename T>
277 template <
typename Range>
284 template <
typename Range>
287 template <
typename Formatter>
289 -> decltype(
f.set_debug_format(
set)) {
290 f.set_debug_format(
set);
292 template <
typename Formatter>
306 template <
typename T>
310 ctx.advance_to(
f.format(v,
ctx));
331 template <
typename Tuple,
typename Char>
334 fmt::is_tuple_formattable<Tuple, Char>::value>> {
336 decltype(detail::tuple::get_formatters<Tuple, Char>(
354 opening_bracket_ = open;
355 closing_bracket_ = close;
358 template <
typename ParseContext>
360 auto it = ctx.begin();
361 if (it != ctx.end() && *it !=
'}')
362 FMT_THROW(format_error(
"invalid format specifier"));
367 template <
typename FormatContext>
368 auto format(
const Tuple& value, FormatContext& ctx)
const
369 -> decltype(ctx.out()) {
370 ctx.advance_to(detail::copy_str<Char>(opening_bracket_, ctx.out()));
374 return detail::copy_str<Char>(closing_bracket_, ctx.out());
378 template <
typename T,
typename Char>
struct is_range {
381 !std::is_convertible<T, std::basic_string<Char>>
::value &&
382 !std::is_convertible<T, detail::std_string_view<Char>>
::value;
389 template <
typename T,
392 return static_cast<T&&
>(
value);
394 template <
typename T,
402 template <
typename Char,
typename Element>
405 std::declval<Element>()))>,
408 template <
typename R>
413 #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
414 template <
typename R,
typename Char>
422 template <
typename P1,
typename... Pn>
426 template <
typename T,
typename Char,
typename Enable =
void>
429 template <
typename T,
typename Char>
455 opening_bracket_ = open;
456 closing_bracket_ = close;
459 template <
typename ParseContext>
461 auto it = ctx.begin();
462 auto end = ctx.end();
464 if (it != end && *it ==
'n') {
465 set_brackets({}, {});
469 if (it != end && *it !=
'}') {
470 if (*it !=
':')
FMT_THROW(format_error(
"invalid format specifier"));
477 return underlying_.parse(ctx);
480 template <
typename R,
typename FormatContext>
481 auto format(R&& range, FormatContext& ctx)
const -> decltype(ctx.out()) {
483 auto out = ctx.out();
484 out = detail::copy_str<Char>(opening_bracket_, out);
488 for (; it != end; ++it) {
489 if (i > 0) out = detail::copy_str<Char>(separator_, out);
492 out = underlying_.format(mapper.
map(item), ctx);
495 out = detail::copy_str<Char>(closing_bracket_, out);
503 template <
typename T>
505 : std::integral_constant<range_format,
506 std::is_same<uncvref_type<T>, T>::value
507 ? range_format::disabled
508 : is_map<T>::value ? range_format::map
509 : is_set<T>::value ? range_format::set
510 : range_format::sequence> {};
512 template <range_format K,
typename R,
typename Char,
typename Enable =
void>
515 template <range_format K>
518 template <range_format K,
typename R,
typename Char>
536 underlying_.underlying().set_brackets({}, {});
537 underlying_.underlying().set_separator(
543 template <
typename ParseContext>
545 return underlying_.parse(ctx);
548 template <
typename FormatContext>
550 -> decltype(ctx.out()) {
551 return underlying_.format(range, ctx);
556 template <
typename T,
typename Char,
typename Enable =
void>
559 is_range<T, Char>::value, detail::range_format_kind_<T>,
560 std::integral_constant<range_format, range_format::disabled>> {};
562 template <
typename R,
typename Char>
568 #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
588 #ifndef FMT_TUPLE_JOIN_SPECIFIERS
589 # define FMT_TUPLE_JOIN_SPECIFIERS 0
592 template <
typename Char,
typename... T>
594 template <
typename ParseContext>
596 return do_parse(ctx, std::integral_constant<
size_t,
sizeof...(T)>());
599 template <
typename FormatContext>
601 FormatContext& ctx)
const ->
typename FormatContext::iterator {
602 return do_format(value, ctx,
603 std::integral_constant<
size_t,
sizeof...(T)>());
609 template <
typename ParseContext>
611 std::integral_constant<size_t, 0>)
612 -> decltype(ctx.begin()) {
616 template <
typename ParseContext,
size_t N>
618 std::integral_constant<size_t, N>)
619 -> decltype(ctx.begin()) {
620 auto end = ctx.begin();
621 #if FMT_TUPLE_JOIN_SPECIFIERS
622 end =
std::get<
sizeof...(T) - N>(formatters_).parse(ctx);
624 auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
626 FMT_THROW(format_error(
"incompatible format specs for tuple elements"));
632 template <
typename FormatContext>
634 std::integral_constant<size_t, 0>)
const ->
635 typename FormatContext::iterator {
639 template <
typename FormatContext,
size_t N>
641 std::integral_constant<size_t, N>)
const ->
642 typename FormatContext::iterator {
643 auto out =
std::get<
sizeof...(T) - N>(formatters_)
644 .format(
std::get<
sizeof...(T) - N>(value.tuple), ctx);
646 out =
std::copy(value.sep.begin(), value.sep.end(), out);
648 return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
658 template <
typename U>
static auto check(U* p) ->
typename U::container_type;
659 template <
typename>
static void check(...);
663 !std::is_void<decltype(check<T>(
nullptr))>::
value;
666 template <
typename Container>
struct all {
668 auto begin() const -> typename Container::const_iterator {
return c.begin(); }
669 auto end() const -> typename Container::const_iterator {
return c.end(); }
673 template <
typename T,
typename Char>
678 range_format::disabled>>::value>>
679 :
formatter<detail::all<typename T::container_type>, Char> {
681 template <
typename FormatContext>
682 auto format(
const T& t, FormatContext& ctx)
const -> decltype(ctx.out()) {
684 static auto get(
const T& t) ->
all {
685 return {t.*(&getter::c)};
705 template <
typename... T>
711 template <
typename... T>
729 template <
typename T>
732 return join(std::begin(list), std::end(list), sep);
738 #endif // FMT_RANGES_H_