Skip to content

Commit

Permalink
include/types_fmt: use fmt::join() to format containers
Browse files Browse the repository at this point in the history
* 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 fmtlib/fmt#2040 and
  fmtlib/fmt#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 <tchaikov@gmail.com>
  • Loading branch information
tchaikov committed Jul 25, 2022
1 parent 3c68057 commit 8de28af
Showing 1 changed file with 46 additions and 33 deletions.
79 changes: 46 additions & 33 deletions src/include/types_fmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,79 @@

#include "include/types.h"

#if FMT_VERSION >= 60000 && FMT_VERSION < 80000
namespace detail {
template <typename T, class = void>
struct is_streamable : std::false_type {};

template <typename T>
struct is_streamable<T, std::void_t<decltype(std::declval<std::ostream>() << *(T*)0)>>
: std::true_type {};
}
template <class T>
struct fmt::formatter<T, std::enable_if_t<detail::is_streamable<T>::value>>
: formatter<std::string_view> {
template <typename Context>
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<std::string_view>::format(str, ctx);
}
};
#endif

template <class Key, class T>
struct fmt::formatter<std::pair<const Key, T>> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

template <typename FormatContext>
auto format(const std::pair<const Key, T>& p, FormatContext& ctx)
{
return fmt::format_to(ctx.out(), "{}={}", p.first, p.second);
}
};

template <class A, class B, class Comp, class Alloc>
struct fmt::formatter<std::map<A, B, Comp, Alloc>> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

template <typename FormatContext>
auto format(const std::map<A, B, Comp, Alloc>& 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 <class A>
struct fmt::formatter<std::list<A>> {
template <class... Args>
struct fmt::formatter<std::list<Args...>> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

template <typename FormatContext>
auto format(const std::list<A>& l, FormatContext& ctx)
auto format(const std::list<Args...>& 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 <class A>
struct fmt::formatter<std::vector<A>> {
template <class... Args>
struct fmt::formatter<std::vector<Args...>> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

template <typename FormatContext>
auto format(const std::vector<A>& l, FormatContext& ctx)
auto format(const std::vector<Args...>& 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 <class A>
struct fmt::formatter<std::set<A>> {
template <class... Args>
struct fmt::formatter<std::set<Args...>> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

template <typename FormatContext>
auto format(const std::set<A>& l, FormatContext& ctx)
auto format(const std::set<Args...>& 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, ","));
}
};

0 comments on commit 8de28af

Please sign in to comment.