diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index c48f1727..b603d637 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -157,6 +157,9 @@ template void for_each(Tuple&& tup, F&& f) { for_each(indexes, std::forward(tup), std::forward(f)); } +template +using value_type = remove_cvref_t().begin())>; + template ::type>::value)> FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) { @@ -182,7 +185,6 @@ FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) { FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) { return add_space ? L" '{}'" : L"'{}'"; } - } // namespace detail template struct is_tuple_like { @@ -246,9 +248,15 @@ template struct is_range { !std::is_constructible, T>::value; }; -template -struct formatter::value>> { +template +struct formatter< + T, Char, + enable_if_t::value +// Workaround a bug in MSVC 2017 and earlier. +#if !FMT_MSC_VER || FMT_MSC_VER >= 1927 + && has_formatter, format_context>::value +#endif + >> { formatting_range formatting; template @@ -257,8 +265,7 @@ struct formatter - typename FormatContext::iterator format(const RangeT& values, - FormatContext& ctx) { + typename FormatContext::iterator format(const T& values, FormatContext& ctx) { auto out = detail::copy(formatting.prefix, ctx.out()); size_t i = 0; auto it = values.begin(); diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 19122047..ae5bf51e 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -141,13 +141,16 @@ TEST(RangesTest, FormatStringLike) { #endif // FMT_USE_STRING_VIEW struct zstring_sentinel {}; + bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; } bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; } + struct zstring { const char* p; const char* begin() const { return p; } zstring_sentinel end() const { return {}; } }; + TEST(RangesTest, JoinSentinel) { zstring hello{"hello"}; EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello)); @@ -189,3 +192,12 @@ TEST(RangesTest, JoinRange) { const std::vector z(3u, 0); EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ","))); } + +#if !FMT_MSC_VER || FMT_MSC_VER >= 1927 +struct unformattable {}; + +TEST(RangesTest, UnformattableRange) { + EXPECT_FALSE((fmt::has_formatter, + fmt::format_context>::value)); +} +#endif