How do I use std::formatter directly?

457 views Asked by At

Let's say I want to format a single object directly using std::formatter, bypassing std::format. How do I do that?

According to Formatter, I need to call .format(value, format_ctx), where format_ctx is a std::format_context or std::basic_format_context<...>. But how do I construct this context?

The standard doesn't seem to provide a way to construct one. And looking at libstdc++ sources, the member variables of basic_format_context are all private, there's no non-default constructor, and no way to set them without being a friend.

Does this mean that std::formatter is impossible to use manually by design?


Why am I doing this?

I want to format a value using the "debug format" ("{?:}") if it's supported, falling back to the regular "{}".

The way to check for support seems to be requires(std::formatter<T> f){f.set_debug_format();}, and I figured that if I'm already interacting with the formatter directly, I might as well use only the formatter itself.

1

There are 1 answers

1
Brian Bi On BEST ANSWER

The use case you're describing, where you never actually call std::(v)format(_to) and just use the formatter directly, isn't supported. You should just call std::format with the format string that you want to use, i.e., {} or {:?}.

And even if you could bypass std::format, you would just be creating work for yourself. You'd have to call std::formatter<T>::parse and std::formatter<T>:format manually (since the former sets up state that is used by the latter). And you'd have to manually set up the contents of the std::basic_format_parse_context and std::basic_format_context objects, assuming that they supported that in the first place.

On the other hand, a formatter can invoke another formatter, by passing down the std::basic_format_parse_context and later the std::basic_format_context that were passed to it by the library. That's basically how you'd implement a range formatter (if it weren't for the fact that the standard already provides one).