diff --git a/include/fmt/format.h b/include/fmt/format.h index f47f64278dea..8525b8237989 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3674,21 +3674,39 @@ struct arg_join : detail::view { : begin(b), end(e), sep(s) {} }; +template +using iterator_arg_mapper = detail::arg_mapper; + +template +using iterator_format_type = + decltype(std::declval>().map( + std::declval::value_type>())); + +template +using iterator_formatter = conditional_t< + has_formatter, + FMT_BUFFER_CONTEXT(Char)>::value, + formatter, Char>, + detail::fallback_formatter, Char>>; + template struct formatter, Char> - : formatter::value_type, Char> { + : iterator_formatter { template auto format(const arg_join& value, FormatContext& ctx) -> decltype(ctx.out()) { - using base = formatter::value_type, Char>; + using base = iterator_formatter; + + iterator_arg_mapper mapper; + auto it = value.begin; auto out = ctx.out(); if (it != value.end) { - out = base::format(*it++, ctx); + out = base::format(mapper.map(*it++), ctx); while (it != value.end) { out = detail::copy_str(value.sep.begin(), value.sep.end(), out); ctx.advance_to(out); - out = base::format(*it++, ctx); + out = base::format(mapper.map(*it++), ctx); } } return out; diff --git a/test/format-test.cc b/test/format-test.cc index 49886eaf3960..997945556e98 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1761,6 +1762,20 @@ TEST(FormatTest, JoinArg) { #endif } +TEST(FormatTest, JoinByte) { + using fmt::join; +#if __cplusplus >= 201703L + using byte = std::byte; +#else + enum class byte : unsigned char {}; +#endif + + std::vector v = {std::byte{0x1}, std::byte{0x2}}; + + EXPECT_EQ("(1, 2)", format("({})", join(v, ", "))); + EXPECT_EQ("(0x1, 0x2)", format("({0:#x})", join(v, ", "))); +} + template std::string str(const T& value) { return fmt::format("{}", value); } diff --git a/test/ostream-test.cc b/test/ostream-test.cc index 7642c94b8438..bf6a228c87b2 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -188,6 +188,11 @@ TEST(OStreamTest, Join) { EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v, v + 3, ", "))); } +TEST(OStreamTest, JoinCustom) { + auto strs = std::vector{TestString("foo"), TestString("bar")}; + EXPECT_EQ("foo, bar", fmt::format("{}", fmt::join(strs, ", "))); +} + #if FMT_USE_CONSTEXPR TEST(OStreamTest, ConstexprString) { EXPECT_EQ("42", format(FMT_STRING("{}"), std::string("42")));