Closed cruisercoder closed 2 months ago
You could pass format_context
or format_context::iterator
to the virtual format
functions and format directly into the underlying buffer via format_to
instead of a temporary string.
That makes sense. The part that was unclear is the construction of the OutputIt return type of the formatter format function (and whether it needed to be returned from the inner format). It looks the return value is for convenience and it's happy to construct from ctx.out(). Updated code below.
class Variant {
public:
template <class X> Variant(const X &x) : ptr_(std::make_shared<model<X>>(x)) {}
void format(fmt::format_context &ctx) const { return ptr_->format(ctx); }
private:
struct base {
virtual ~base() {}
virtual void format(fmt::format_context &ctx) const = 0;
};
template <class X> struct model : public base {
model(const X &x) : x_(x) {}
void format(fmt::format_context &ctx) const override {fmt::format_to(ctx.out(), "{}", x_); }
X x_;
};
using ptr_t = std::shared_ptr<base>;
ptr_t ptr_;
};
template <> struct fmt::formatter<Variant> {
constexpr auto parse(fmt::format_parse_context &context) { return context.begin(); }
auto format(const Variant &v, fmt::format_context &ctx) const {
v.format(ctx);
return ctx.out();
}
};
You don't have to return the iterator in this case because format_context::iterator
is like a back_insert_iterator
into an output buffer.
For garden variety user variant types that hold other types (with private inheritance, for example), what is the suggested way to implement calls for formatting of the underlying types? Can I do better than calling a function that returns the string value of format() of the underlying typed value? Is there a better runtime mechanism that uses the format_context in some way?