diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 678df0f1032e..b40a68dfe521 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -164,7 +164,13 @@ using make_index_sequence = make_integer_sequence; template using tuple_index_sequence = make_index_sequence::value>; -template ::value> +template +struct has_format_as_ : std::false_type {}; +template +struct has_format_as_>> : std::true_type {}; + +template ::value && !has_format_as_::value> class is_tuple_formattable_ { public: static constexpr bool value = false; @@ -297,10 +303,20 @@ template struct is_tuple_formattable { static constexpr bool value = detail::is_tuple_formattable_::value; }; +namespace detail { +template ::value> +struct is_tuple_formattable_for_formatter : std::false_type {}; + +template +struct is_tuple_formattable_for_formatter + : std::integral_constant::value> {}; +} // namespace detail + template struct formatter::value && - fmt::is_tuple_formattable::value>> { + detail::is_tuple_formattable_for_formatter< + Tuple, Char>::value>> { private: decltype(detail::tuple::get_formatters( detail::tuple_index_sequence())) formatters_; diff --git a/test/ranges-test.cc b/test/ranges-test.cc index d3ca6498faac..9cdbb2019514 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -721,6 +721,23 @@ TEST(ranges_test, format_as_tie) { EXPECT_EQ(fmt::format("{}", tieable()), "(3, 0.42)"); } +struct format_as_tuple_like {}; + +auto format_as(const format_as_tuple_like&) -> std::string { return "Hello"; } + +namespace std { +template <> struct tuple_size + : integral_constant {}; +template <> struct tuple_element<0, format_as_tuple_like> { + using type = format_as_tuple_like; +}; +} // namespace std + +TEST(ranges_test, format_as_tuple_like) { + EXPECT_TRUE((fmt::is_formattable::value)); + EXPECT_EQ(fmt::format("{}", format_as_tuple_like{}), "Hello"); +} + struct lvalue_qualified_begin_end { int arr[5] = {1, 2, 3, 4, 5};