mirror of
https://github.com/fmtlib/fmt.git
synced 2026-10-29 02:17:28 +08:00
Move has_format_as to format.h and use it in the tuple formatter
The tuple formatter had a bespoke trait to keep format_as from producing an ambiguous specialization. detail::has_format_as already answers that question and std.h applies it the same way, so move it from std.h to format.h where ranges.h can see it and drop the extra trait. Check it with conditional_t rather than &&: is_tuple_formattable must not be instantiated for types with format_as because for self-referential tuple-like types that recurses back into formatter selection, and && short-circuits evaluation but not instantiation.
This commit is contained in:
parent
cfb57bfa3a
commit
79e48ba915
@ -4100,6 +4100,11 @@ template <typename Char> class nested_format_specs {
|
||||
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_format_as : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_format_as<T, void_t<format_as_result<T>>> : std::true_type {};
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
@ -297,21 +297,17 @@ template <typename T, typename C> struct is_tuple_formattable {
|
||||
static constexpr bool value = detail::is_tuple_formattable_<T, C>::value;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename C, typename = void>
|
||||
struct is_tuple_formattable_for_formatter
|
||||
: std::integral_constant<bool, fmt::is_tuple_formattable<T, C>::value> {};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct is_tuple_formattable_for_formatter<T, C, void_t<format_as_result<T>>>
|
||||
: std::false_type {};
|
||||
} // namespace detail
|
||||
|
||||
template <typename Tuple, typename Char>
|
||||
struct formatter<Tuple, Char,
|
||||
enable_if_t<fmt::is_tuple_like<Tuple>::value &&
|
||||
detail::is_tuple_formattable_for_formatter<
|
||||
Tuple, Char>::value>> {
|
||||
struct formatter<
|
||||
Tuple, Char,
|
||||
// format_as takes precedence. conditional_t rather than && because
|
||||
// is_tuple_formattable must not be instantiated for types with format_as:
|
||||
// for self-referential tuple-like types it recurses back into this
|
||||
// specialization.
|
||||
enable_if_t<
|
||||
fmt::is_tuple_like<Tuple>::value &&
|
||||
conditional_t<detail::has_format_as<Tuple>::value, std::false_type,
|
||||
fmt::is_tuple_formattable<Tuple, Char>>::value>> {
|
||||
private:
|
||||
decltype(detail::tuple::get_formatters<Tuple, Char>(
|
||||
detail::tuple_index_sequence<Tuple>())) formatters_;
|
||||
|
||||
@ -279,12 +279,6 @@ struct is_bit_reference_like<std::__bit_const_reference<C>> {
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_format_as : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_format_as<T, void_t<decltype(format_as(std::declval<const T&>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_format_as_member : std::false_type {};
|
||||
template <typename T>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user