Arnaud
Arnaud

Reputation: 651

Problem with Formatting User-defined Types with fmt library

I faced a problem for formatting a user-defined type and ended up with this simple example based on fmt documentation.

struct point_double {
    double x, y;

    operator const char*() const {
        return nullptr;
    }
};

namespace fmt {
template <>
struct formatter<point_double> {
    template <typename ParseContext>
    constexpr auto parse(ParseContext& ctx) {
        return ctx.begin();
    }

    template <typename FormatContext>
    auto format(const point_double& p, FormatContext& ctx) {
        return format_to(ctx.out(), "({:.1f}, {:.1f})", p.x, p.y);
    }
};
}  // namespace fmt

void foo() {
    point_double p = {1, 2};
    fmt::print("{}\n", p);
}

Calling foo will crash because the user-defined formatter is not used. Instead fmt::print will use the default string formatter and crash as the operator returns nullptr. Is there a way to go around this issue? I'm using fmt 5.3.0

Upvotes: 2

Views: 1468

Answers (1)

vitaut
vitaut

Reputation: 55595

You cannot have both an implicit conversion to const char* and a formatter specialization ({fmt} will now give you a compile-time error), because const char* is already formattable. If you have control over point_double, an easy solution is to make the conversion operator explicit which is a good idea in general. Otherwise you can wrap point_double in another type and provide a formatter specialization for that.

Upvotes: 1

Related Questions