From 8de28af6464b6271fa32d1f11cfa858d478debdf Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 25 Jul 2022 00:16:33 +0800 Subject: [PATCH] include/types_fmt: use fmt::join() to format containers * add formatter for classes with stream insertion operator. as in fmtlib v6.1.2, which is the one shipped with ubuntu focal, fmt::join() requires the printed element to have formatter. see https://github.com/fmtlib/fmt/issues/2040 and https://github.com/fmtlib/fmt/issues/1462 * use template parameter pack to represent container template argument, simpler this way. also, this enables us to print specialized classes which uses non-default template parameters. * use fmt::join() to print container elements. see also https://fmt.dev/latest/api.html#_CPPv4I0EN3fmt4joinE9join_viewIN6detail10iterator_tI5RangeEEN6detail10sentinel_tI5RangeEEERR5Range11string_view Signed-off-by: Kefu Chai --- src/include/types_fmt.h | 79 ++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/src/include/types_fmt.h b/src/include/types_fmt.h index 5f33248a9839bd..f3f57115129701 100644 --- a/src/include/types_fmt.h +++ b/src/include/types_fmt.h @@ -11,6 +11,39 @@ #include "include/types.h" +#if FMT_VERSION >= 60000 && FMT_VERSION < 80000 +namespace detail { + template + struct is_streamable : std::false_type {}; + + template + struct is_streamable() << *(T*)0)>> + : std::true_type {}; +} +template +struct fmt::formatter::value>> + : formatter { + template + auto format(const T& value, Context& ctx) { + memory_buffer buffer; + format_value(buffer, value, ctx.locale()); + std::string_view str(buffer.data(), buffer.size()); + return formatter::format(str, ctx); + } +}; +#endif + +template +struct fmt::formatter> { + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + + template + auto format(const std::pair& p, FormatContext& ctx) + { + return fmt::format_to(ctx.out(), "{}={}", p.first, p.second); + } +}; + template struct fmt::formatter> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } @@ -18,59 +51,39 @@ struct fmt::formatter> { template auto format(const std::map& m, FormatContext& ctx) { - std::string_view sep = "{"; - for (const auto& [k, v] : m) { - fmt::format_to(ctx.out(), "{}{}={}", sep, k, v); - sep = ","; - } - return fmt::format_to(ctx.out(), "}}"); + return fmt::format_to(ctx.out(), "{{{}}}", fmt::join(m, ",")); } }; -template -struct fmt::formatter> { +template +struct fmt::formatter> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template - auto format(const std::list& l, FormatContext& ctx) + auto format(const std::list& l, FormatContext& ctx) { - std::string_view sep = ""; - for (const auto& e : l) { - fmt::format_to(ctx.out(), "{}{}", sep, e); - sep = ","; - } - return ctx.out(); + return fmt::format_to(ctx.out(), "{}", fmt::join(l, ",")); } }; -template -struct fmt::formatter> { +template +struct fmt::formatter> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template - auto format(const std::vector& l, FormatContext& ctx) + auto format(const std::vector& v, FormatContext& ctx) { - std::string_view sep = "["; - for (const auto& e : l) { - fmt::format_to(ctx.out(), "{}{}", sep, e); - sep = ","; - } - return fmt::format_to(ctx.out(), "]"); + return fmt::format_to(ctx.out(), "[{}]", fmt::join(v, ",")); } }; -template -struct fmt::formatter> { +template +struct fmt::formatter> { constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } template - auto format(const std::set& l, FormatContext& ctx) + auto format(const std::set& s, FormatContext& ctx) { - std::string_view sep = ""; - for (const auto& e : l) { - fmt::format_to(ctx.out(), "{}{}", sep, e); - sep = ","; - } - return ctx.out(); + return fmt::format_to(ctx.out(), "{}", fmt::join(s, ",")); } };