Search code examples
c++fmt

Adding custom type formatting, with all the usual options


I've made a Decimal class and want to use the fmt library. I read that the way to define a type to the formatter is to specialize fmt::formatter. But, there is no information in the docs on how to call into the existing common infrastructure. The formatting codes for field alignment and overall width and fill character, for example: that should be common code that works across any type.
How do I write a formatter specialization without re-implementing the entire specification from scratch?

I'd like to start by making my type compatible with the floating-point formatting specifiers, so when a type is changed from double to decimal it will continue to work the same; but then add additional features specific to the type.

template <int S, int F>
struct fmt::formatter<Decimal<S,F>> {

constexpr auto parse(format_parse_context& ctx) {
    [[maybe_unused]] auto it = ctx.begin(), end = ctx.end();
    // dummy stub.  just take the whole thing
    it = std::find(ctx.begin(),end, '}');
    return it;
}

template <typename FormatContext>
auto format(const Dec& x, FormatContext& ctx) {
    constexpr size_t bufsize = 64;
    char buf[bufsize];
    const auto end = x.to_chars (buf, buf+bufsize, false);
    const std::string_view sv { buf, size_t(end-buf) };
    return std::copy(sv.begin(),sv.end(),ctx.out());
}
};

Solution

  • {fmt} doesn't yet provide facilities for parsing standard format specifiers. Internally it uses fmt::detail::parse_format_specs. It needs to be cleaned up a bit and moved to the public API for reuse.