From 568233889171e0ee91bf28879b1482b038e84cc2 Mon Sep 17 00:00:00 2001 From: jehelset <47066444+jehelset@users.noreply.github.com> Date: Sun, 19 Jun 2022 17:25:58 +0200 Subject: [PATCH] Fix is_formattable for tuple-like types. (#2940) --- include/fmt/ranges.h | 34 +++++++++++++++++++++++++++++++++- test/ranges-test.cc | 12 +++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index a1fc80d2..4f65eb4b 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -202,6 +202,31 @@ template using make_index_sequence = make_integer_sequence; #endif +template +using tuple_index_sequence = make_index_sequence::value>; + +template ::value> +class is_tuple_formattable_ { + public: + static constexpr const bool value = false; +}; +template class is_tuple_formattable_ { + template + static std::true_type check2(index_sequence, + integer_sequence); + static std::false_type check2(...); + template + static decltype(check2( + index_sequence{}, + integer_sequence< + bool, (is_formattable::type, + C>::value)...>{})) check(index_sequence); + + public: + static constexpr const bool value = + decltype(check(tuple_index_sequence{}))::value; +}; + template void for_each(index_sequence, Tuple&& tup, F&& f) noexcept { using std::get; @@ -283,8 +308,15 @@ template struct is_tuple_like { detail::is_tuple_like_::value && !detail::is_range_::value; }; +template struct is_tuple_formattable { + static constexpr const bool value = + detail::is_tuple_formattable_::value; +}; + template -struct formatter::value>> { +struct formatter::value && + fmt::is_tuple_formattable::value>> { private: // C++11 generic lambda for format(). template struct format_each { diff --git a/test/ranges-test.cc b/test/ranges-test.cc index cdc6930d..468e4f40 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -85,11 +85,22 @@ TEST(ranges_test, format_pair) { EXPECT_EQ(fmt::format("{}", p), "(42, 1.5)"); } +struct unformattable {}; + TEST(ranges_test, format_tuple) { auto t = std::tuple(42, 1.5f, "this is tuple", 'i'); EXPECT_EQ(fmt::format("{}", t), "(42, 1.5, \"this is tuple\", 'i')"); EXPECT_EQ(fmt::format("{}", std::tuple<>()), "()"); + + EXPECT_TRUE((fmt::is_formattable>::value)); + EXPECT_FALSE((fmt::is_formattable::value)); + EXPECT_FALSE((fmt::is_formattable>::value)); + EXPECT_FALSE((fmt::is_formattable>::value)); + EXPECT_FALSE((fmt::is_formattable>::value)); + EXPECT_FALSE( + (fmt::is_formattable>::value)); + EXPECT_TRUE((fmt::is_formattable>::value)); } #ifdef FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT @@ -220,7 +231,6 @@ TEST(ranges_test, enum_range) { } #if !FMT_MSC_VERSION -struct unformattable {}; TEST(ranges_test, unformattable_range) { EXPECT_FALSE((fmt::has_formatter,