12# include <initializer_list>
15# include <type_traits>
23enum class range_format { disabled, map, set, sequence, string, debug_string };
28 template <
typename U>
static auto check(U*) ->
typename U::mapped_type;
29 template <
typename>
static void check(...);
32 static constexpr const bool value =
33 !std::is_void<decltype(check<T>(
nullptr))>::value;
37 template <
typename U>
static auto check(U*) ->
typename U::key_type;
38 template <
typename>
static void check(...);
41 static constexpr const bool value =
47template <
typename T,
typename _ =
void>
struct is_range_ : std::false_type {};
49#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
51# define FMT_DECLTYPE_RETURN(val) \
52 ->decltype(val) { return val; } \
58template <
typename T, std::
size_t N>
59auto range_begin(
const T (&arr)[N]) ->
const T* {
62template <
typename T, std::
size_t N>
63auto range_end(
const T (&arr)[N]) ->
const T* {
67template <
typename T,
typename Enable =
void>
72 decltype(std::declval<T>().end())>>
77auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(
static_cast<T&&
>(rng).begin());
79auto range_end(T&& rng) FMT_DECLTYPE_RETURN(
static_cast<T&&
>(rng).end());
84auto range_begin(T&& rng)
85 -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
86 decltype(begin(
static_cast<T&&
>(rng)))> {
87 return begin(
static_cast<T&&
>(rng));
90auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
91 decltype(end(
static_cast<T&&
>(rng)))> {
92 return end(
static_cast<T&&
>(rng));
95template <
typename T,
typename Enable =
void>
97template <
typename T,
typename Enable =
void>
104 decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
105 decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
110 T, void_t<decltype(detail::range_begin(std::declval<T&>())),
111 decltype(detail::range_end(std::declval<T&>())),
114 int>> : std::true_type {};
118 : std::integral_constant<bool, (has_const_begin_end<T>::value ||
119 has_mutable_begin_end<T>::value)> {};
120# undef FMT_DECLTYPE_RETURN
125 template <
typename U>
126 static auto check(U* p) ->
decltype(std::tuple_size<U>::value, int());
127 template <
typename>
static void check(...);
130 static constexpr const bool value =
131 !std::is_void<decltype(check<T>(
nullptr))>::value;
135#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
136template <
typename T, T... N>
138template <
size_t... N>
using index_sequence = std::index_sequence<N...>;
142 using value_type = T;
144 static FMT_CONSTEXPR
auto size() ->
size_t {
return sizeof...(N); }
149template <
typename T,
size_t N, T... Ns>
151template <
typename T, T... Ns>
161template <typename T, typename C, bool = is_tuple_like_<T>::value>
164 static constexpr const bool value =
false;
167 template <
size_t... Is>
170 static auto all_true(...) -> std::false_type;
172 template <
size_t... Is>
176 (is_formattable<typename std::tuple_element<Is, T>::type,
180 static constexpr const bool value =
184template <
typename Tuple,
typename F,
size_t... Is>
188 const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
189 ignore_unused(unused);
192template <
typename Tuple,
typename F>
193FMT_CONSTEXPR
void for_each(Tuple&& t, F&& f) {
194 for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
195 std::forward<Tuple>(t), std::forward<F>(f));
198template <
typename Tuple1,
typename Tuple2,
typename F,
size_t... Is>
199void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
201 const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
202 ignore_unused(unused);
205template <
typename Tuple1,
typename Tuple2,
typename F>
206void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
207 for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
208 std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
214template <
typename Char,
typename... T>
215using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
218template <
typename Tuple,
typename Char, std::size_t... Is>
219auto get_formatters(index_sequence<Is...>)
220 -> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
223#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
225template <
typename R>
struct range_reference_type_impl {
226 using type =
decltype(*detail::range_begin(std::declval<R&>()));
229template <
typename T, std::
size_t N>
struct range_reference_type_impl<T[N]> {
234using range_reference_type =
typename range_reference_type_impl<T>::type;
236template <
typename Range>
237using range_reference_type =
238 decltype(*detail::range_begin(std::declval<Range&>()));
243template <
typename Range>
244using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
246template <
typename Formatter>
247FMT_CONSTEXPR
auto maybe_set_debug_format(Formatter& f,
bool set)
248 ->
decltype(f.set_debug_format(set)) {
249 f.set_debug_format(set);
251template <
typename Formatter>
252FMT_CONSTEXPR
void maybe_set_debug_format(Formatter&, ...) {}
256 : std::integral_constant<range_format,
257 std::is_same<uncvref_type<T>, T>::value
258 ? range_format::disabled
259 : is_map<T>::value ? range_format::map
260 : is_set<T>::value ? range_format::set
261 : range_format::sequence> {};
263template <range_format K>
264using range_format_constant = std::integral_constant<range_format, K>;
268 template <
typename Formatter> FMT_CONSTEXPR
void operator()(Formatter& f) {
270 detail::maybe_set_debug_format(f,
true);
275 using char_type =
typename FormatContext::char_type;
277 template <
typename T>
279 if (i > 0) ctx.advance_to(detail::copy<char_type>(separator, ctx.out()));
280 ctx.advance_to(f.format(v, ctx));
292 static constexpr const bool value =
297 static constexpr const bool value =
301template <
typename Tuple,
typename Char>
304 fmt::is_tuple_formattable<Tuple, Char>::value>> {
306 decltype(detail::tuple::get_formatters<Tuple, Char>(
324 opening_bracket_ = open;
325 closing_bracket_ = close;
328 template <
typename ParseContext>
329 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
330 auto it = ctx.begin();
331 if (it != ctx.end() && *it !=
'}') report_error(
"invalid format specifier");
336 template <
typename FormatContext>
337 auto format(
const Tuple& value, FormatContext& ctx)
const
338 ->
decltype(ctx.out()) {
339 ctx.advance_to(detail::copy<Char>(opening_bracket_, ctx.out()));
343 return detail::copy<Char>(closing_bracket_, ctx.out());
347template <
typename T,
typename Char>
struct is_range {
348 static constexpr const bool value =
356 template <
typename T,
357 FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
358 static auto map(T&&
value) -> T&& {
359 return static_cast<T&&
>(
value);
361 template <
typename T,
362 FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
363 static auto map(T&&
value)
364 ->
decltype(
mapper().map(
static_cast<T&&
>(
value))) {
369template <
typename Char,
typename Element>
372 .map(std::declval<Element>()))>,
376using maybe_const_range =
377 conditional_t<has_const_begin_end<R>::value,
const R, R>;
380#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
381template <
typename R,
typename Char>
383 : is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
389template <
typename P1,
typename... Pn>
391 : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
393template <
typename T,
typename Char,
typename Enable =
void>
396template <
typename T,
typename Char>
399 enable_if_t<
conjunction<std::is_same<T, remove_cvref_t<T>>,
400 is_formattable<T, Char>>::value>> {
408 bool is_debug =
false;
410 template <
typename Output,
typename It,
typename Sentinel,
typename U = T,
411 FMT_ENABLE_IF(std::is_same<U, Char>::value)>
412 auto write_debug_string(Output& out, It it, Sentinel end)
const -> Output {
414 for (; it != end; ++it) buf.push_back(*it);
416 specs.type = presentation_type::debug;
417 return detail::write<Char>(
421 template <
typename Output,
typename It,
typename Sentinel,
typename U = T,
422 FMT_ENABLE_IF(!std::is_same<U, Char>::value)>
423 auto write_debug_string(Output& out, It, Sentinel)
const -> Output {
440 opening_bracket_ = open;
441 closing_bracket_ = close;
444 template <
typename ParseContext>
445 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
446 auto it = ctx.begin();
447 auto end = ctx.end();
448 detail::maybe_set_debug_format(underlying_,
true);
449 if (it == end)
return underlying_.parse(ctx);
451 switch (detail::to_ascii(*it)) {
453 set_brackets({}, {});
458 set_brackets({}, {});
460 if (it == end || *it !=
's') report_error(
"invalid format specifier");
463 if (!std::is_same<T, Char>::value)
464 report_error(
"invalid format specifier");
469 detail::maybe_set_debug_format(underlying_,
false);
475 if (it != end && *it !=
'}') {
476 if (*it !=
':') report_error(
"invalid format specifier");
477 detail::maybe_set_debug_format(underlying_,
false);
482 return underlying_.parse(ctx);
485 template <
typename R,
typename FormatContext>
486 auto format(R&& range, FormatContext& ctx)
const ->
decltype(ctx.out()) {
488 auto out = ctx.out();
489 auto it = detail::range_begin(range);
490 auto end = detail::range_end(range);
491 if (is_debug)
return write_debug_string(out, it, end);
493 out = detail::copy<Char>(opening_bracket_, out);
495 for (; it != end; ++it) {
496 if (i > 0) out = detail::copy<Char>(separator_, out);
498 out = underlying_.format(mapper.map(*it), ctx);
501 out = detail::copy<Char>(closing_bracket_, out);
506template <
typename T,
typename Char,
typename Enable =
void>
509 is_range<T, Char>::value, detail::range_format_kind_<T>,
510 std::integral_constant<range_format, range_format::disabled>> {};
512template <
typename R,
typename Char>
517 range_format::disabled &&
520#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
526 using range_type = detail::maybe_const_range<R>;
536 template <
typename ParseContext>
537 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
538 return range_formatter_.parse(ctx);
541 template <
typename FormatContext>
542 auto format(range_type& range, FormatContext& ctx)
const
543 ->
decltype(ctx.out()) {
544 return range_formatter_.format(range, ctx);
549template <
typename R,
typename Char>
554 using map_type = detail::maybe_const_range<R>;
555 using element_type = detail::uncvref_type<map_type>;
557 decltype(detail::tuple::get_formatters<element_type, Char>(
559 bool no_delimiters_ =
false;
564 template <
typename ParseContext>
565 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
566 auto it = ctx.begin();
567 auto end = ctx.end();
569 if (detail::to_ascii(*it) ==
'n') {
570 no_delimiters_ =
true;
573 if (it != end && *it !=
'}') {
574 if (*it !=
':') report_error(
"invalid format specifier");
583 template <
typename FormatContext>
584 auto format(map_type& map, FormatContext& ctx)
const ->
decltype(ctx.out()) {
585 auto out = ctx.out();
587 if (!no_delimiters_) out = detail::copy<Char>(open, out);
591 for (
auto&& value : map) {
592 if (i > 0) out = detail::copy<Char>(sep, out);
594 detail::for_each2(formatters_, mapper.map(value),
596 0, ctx, detail::string_literal<Char,
':',
' '>{}});
600 if (!no_delimiters_) out = detail::copy<Char>(close, out);
605template <
typename It,
typename Sentinel,
typename Char =
char>
612 : begin(std::move(b)), end(e), sep(s) {}
615template <
typename It,
typename Sentinel,
typename Char>
619#ifdef __cpp_lib_ranges
620 std::iter_value_t<It>;
622 typename std::iterator_traits<It>::value_type;
626 using view_ref = conditional_t<std::is_copy_constructible<It>::value,
631 using nonlocking = void;
633 template <
typename ParseContext>
634 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
const Char* {
635 return value_formatter_.parse(ctx);
638 template <
typename FormatContext>
639 auto format(view_ref& value, FormatContext& ctx)
const
640 ->
decltype(ctx.out()) {
641 auto it = std::forward<view_ref>(value).begin;
642 auto out = ctx.out();
643 if (it == value.end)
return out;
644 out = value_formatter_.format(*it, ctx);
646 while (it != value.end) {
647 out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
649 out = value_formatter_.format(*it, ctx);
660template <
typename It,
typename Sentinel>
662 return {std::move(begin), end, sep};
681template <
typename Range>
683 ->
join_view<
decltype(detail::range_begin(r)),
684 decltype(detail::range_end(r))> {
685 return {detail::range_begin(r), detail::range_end(r), sep};
689 const std::tuple<T...>& tuple;
693 : tuple(t), sep{s} {}
699#ifndef FMT_TUPLE_JOIN_SPECIFIERS
700# define FMT_TUPLE_JOIN_SPECIFIERS 0
703template <
typename Char,
typename... T>
705 template <
typename ParseContext>
706 FMT_CONSTEXPR
auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
707 return do_parse(ctx, std::integral_constant<
size_t,
sizeof...(T)>());
710 template <
typename FormatContext>
712 FormatContext& ctx)
const ->
typename FormatContext::iterator {
713 return do_format(value, ctx,
714 std::integral_constant<
size_t,
sizeof...(T)>());
718 std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
720 template <
typename ParseContext>
721 FMT_CONSTEXPR
auto do_parse(ParseContext& ctx,
722 std::integral_constant<size_t, 0>)
723 ->
decltype(ctx.begin()) {
727 template <
typename ParseContext,
size_t N>
728 FMT_CONSTEXPR
auto do_parse(ParseContext& ctx,
729 std::integral_constant<size_t, N>)
730 ->
decltype(ctx.begin()) {
731 auto end = ctx.begin();
732#if FMT_TUPLE_JOIN_SPECIFIERS
733 end = std::get<
sizeof...(T) - N>(formatters_).parse(ctx);
735 auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
737 report_error(
"incompatible format specs for tuple elements");
743 template <
typename FormatContext>
745 std::integral_constant<size_t, 0>)
const ->
746 typename FormatContext::iterator {
750 template <
typename FormatContext,
size_t N>
752 std::integral_constant<size_t, N>)
const ->
753 typename FormatContext::iterator {
754 auto out = std::get<
sizeof...(T) - N>(formatters_)
755 .format(std::get<
sizeof...(T) - N>(value.tuple), ctx);
756 if (N <= 1)
return out;
757 out = detail::copy<Char>(value.sep, out);
759 return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
766template <
typename T>
class is_container_adaptor_like {
767 template <
typename U>
static auto check(U* p) ->
typename U::container_type;
768 template <
typename>
static void check(...);
771 static constexpr const bool value =
772 !std::is_void<decltype(check<T>(
nullptr))>::value;
775template <
typename Container>
struct all {
777 auto begin() const -> typename Container::const_iterator {
return c.begin(); }
778 auto end() const -> typename Container::const_iterator {
return c.end(); }
782template <
typename T,
typename Char>
785 enable_if_t<
conjunction<detail::is_container_adaptor_like<T>,
786 bool_constant<range_format_kind<T, Char>::value ==
787 range_format::disabled>>::value>>
788 :
formatter<detail::all<typename T::container_type>, Char> {
789 using all = detail::all<typename T::container_type>;
790 template <
typename FormatContext>
791 auto format(
const T& t, FormatContext& ctx)
const ->
decltype(ctx.out()) {
793 static auto get(
const T& t) -> all {
794 return {t.*(&getter::c)};
814template <
typename... T>
815FMT_CONSTEXPR
auto join(
const std::tuple<T...>& tuple,
string_view sep)
832auto join(std::initializer_list<T> list,
string_view sep)
834 return join(std::begin(list), std::end(list), sep);
GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool all(vec< L, bool, Q > const &v)
Definition func_vector_relational.inl:67
Definition Common3D.hpp:137