Search code examples
c++c++20fmt

Adding Arbitrary Texts to fmt's User-defined Type Formatter


I'm wondering what's the correct way of adding some arbitrary text to fmt::formatter::format. Basically, I want to have a title for my object. The current implementation works but I'm not sure whether it can be done better, also I've a feeling my vertical alignment hack can be done nicer.

namespace fmt {
  template <>
  struct formatter<Experiment> {
    
    constexpr auto parse(format_parse_context& ctx) {
      return ctx.begin();
    }
    
    template <typename FormatContext>
    auto format(const Experiment& e, FormatContext& ctx) {
      ctx.out() = format_to(ctx.out(), "Experiment:\n\t\t\t\t");
      return format_to(ctx.out(),
                       "{}", join(e.begin(), e.end(), "\n\t\t\t\t"));
    }
  };
}

Solution

  • You can copy the text via the output iterator returned by ctx.out():

        template <typename FormatContext>
        auto format(const Experiment& e, FormatContext& ctx) {
          auto out = ctx.out();
          auto text = std::string_view("Experiment:\n\t\t\t\t");
          out = std::copy_n(text.data(), text.size(), out);
          return format_to(out, "{}", join(e.begin(), e.end(), "\n\t\t\t\t"));
        }
    

    Note that assigning to ctx.out() doesn't make much sense because you are assigning to a temporary that gets discarded. Instead you should return the past-the-end iterator from the format function.

    As for alignment, you can use the width format specifier for padding if you know the maximum width.