diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 3068649f207e..71474f325069 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -19,21 +19,6 @@ FMT_BEGIN_NAMESPACE -template struct formatting_range { -#ifdef FMT_DEPRECATED_BRACED_RANGES - Char prefix = '{'; - Char postfix = '}'; -#else - Char prefix = '['; - Char postfix = ']'; -#endif - - template - FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } -}; - template struct formatting_tuple { Char prefix = '('; Char postfix = ')'; @@ -87,7 +72,7 @@ template struct is_std_string_like> : std::true_type {}; template class is_map { - template static auto check(U*) -> typename U::key_type; + template static auto check(U*) -> typename U::mapped_type; template static void check(...); public: @@ -99,6 +84,19 @@ template class is_map { #endif }; +template class is_set { + template static auto check(U*) -> typename U::key_type; + template static void check(...); + + public: +#ifdef FMT_FORMAT_SET_AS_LIST + static FMT_CONSTEXPR_DECL const bool value = false; +#else + static FMT_CONSTEXPR_DECL const bool value = + !std::is_void(nullptr))>::value && !is_map::value; +#endif +}; + template struct conditional_helper {}; template struct is_range_ : std::false_type {}; @@ -602,11 +600,9 @@ struct formatter< detail::has_fallback_formatter, Char>::value) #endif >> { - formatting_range formatting; - template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return formatting.parse(ctx); + return ctx.begin(); } template < @@ -614,17 +610,26 @@ struct formatter< FMT_ENABLE_IF( std::is_same::value, const T, T>>::value)> - auto format(U& values, FormatContext& ctx) -> decltype(ctx.out()) { - auto out = detail::copy(formatting.prefix, ctx.out()); - size_t i = 0; - auto it = std::begin(values); - auto end = std::end(values); + auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) { +#ifdef FMT_DEPRECATED_BRACED_RANGES + Char prefix = '{'; + Char postfix = '}'; +#else + Char prefix = detail::is_set::value ? '{' : '['; + Char postfix = detail::is_set::value ? '}' : ']'; +#endif + auto out = ctx.out(); + *out++ = prefix; + int i = 0; + auto it = std::begin(range); + auto end = std::end(range); for (; it != end; ++it) { if (i > 0) out = detail::write_delimiter(out); out = detail::write_range_entry(out, *it); ++i; } - return detail::copy(formatting.postfix, out); + *out++ = postfix; + return out; } }; diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 4481e2b436e8..86dd5520c7df 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -58,6 +58,11 @@ TEST(ranges_test, format_map) { EXPECT_EQ(fmt::format("{}", m), "{\"one\": 1, \"two\": 2}"); } +TEST(ranges_test, format_set) { + EXPECT_EQ(fmt::format("{}", std::set{"one", "two"}), + "{\"one\", \"two\"}"); +} + TEST(ranges_test, format_pair) { auto p = std::pair(42, 1.5f); EXPECT_EQ(fmt::format("{}", p), "(42, 1.5)");