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.
fmt
does have the public constructors: github.com/fmtlib/fmt/blob/… – Ileanastd::format_context
, alright, butstd::basic_format_context
lets you specify a custom iterator, so I thought I could do that. – Hartsfieldstd::output_iterator<iter, const CharT&>
. It is unlikely that a type specializes for a specific iterator, but very likely that it only specializes forchar
(default). Do you want to specialize on iterator? – Ethnoit=std::format_to(it,fmt,...);
– Ethnostd::formatter
directly. I don't care what iterator it uses internally as long as it works, I'd probably use it withstd::back_inserter
. The only reason why I'm talking about custom iterators is because the default iterator type used bystd::format_context
is unspecified, so I can't use it directly, so I need a different type if I want to constructbasic_format_context
manually. – Hartsfieldstd::formatter
is impossible to use manually by design?" It is abundantly clear thatstd::formatter
is impossible to use manually (portably at least). The standard just doesn't give you any way to construct one. The only remaining question is whether it is by design. I don't know for sure because I don't have relevant design documents, but from the looks of it, it seems so. – Receptionstd::formatter
itself is required to be defaut-constructible. – Hartsfieldformatter ::format
". And it is required to be defaut-constructible because the library should be able to default-construct it. The programmer is not supposed to. – Receptionstd::format_context
doesn't need any magical iterator type. The iterator comes from first argument tostd::format_to
which is an instance ofbasic_string::iterator
identified bybasic_string_view
instance taken frombasic_format_string::get
which in turn is identical to thebasic_string_view
that capturesfmt
. All you need to check about iterator is conceptstd::output_iterator<iter, const CharT&>
. – Ethnostd::formatter
withoutstd::format
(and without any similar functions, such asstd::format_to
). – Hartsfieldformat_to
create the context. If you want to create a temporary context for a range type, then good luck with that: youtu.be/EQELdyecZlU?feature=shared – Ethnoprintfs\scanfs
still stay the most flexible one and libraries with similar capabilities behave either in similar way or use regex flavors. fmt was clearly designed by someone coming from front-end development. – Guiseprintf
has always been an will always be a big nono in C++ . C variadic functions are just relics from the past.scanf
is even worse.{fmt}
is created by a well rounded C++ expert. I might not agree with the design, but it's by far the best we've got. strong type-checking, compact syntax and readability are it's advantages; the only major problem is lack of foresight for genericness and scale.printf
can't even provide minimum extensibility. If I were to design fmt, I'd start with tuple as the primary formatable type. I am no fan of SWIFT; neither Taylor, nor Apple's. – Ethnoprintf
by definition got linear stack footprint and matching time with two forks, by design. – Guisevformat
withformat
.format
prcesses the fmt string at compile-time; So combined withfputs
orfwrite
, it should outperformprintf
. Becauseprintf
must interpret fmt at runtime. – Ethnoformat
) should not be a core constant expression. – Ethno{ arg-id (optional) : format-spec }
theformat-spec
wouldnt be a core constant – Guiseformat
orprintf
. Your seem to be confusing it with return value fromformat
. – Ethnofmt::format("You have {} HP", player_health)
displayed somewhere.player_health
is only known at runtime, so the format string needs to be localized, not the return value. You can't localize"You have "
and" HP"
separately, because that's 1. not convenient, and 2. not feasible if there's >1{}
, since they might need to be reordered in different locales. – Hartsfield"{} {} {}", YouHaveString, HPValue, HpString
. Only that's unworkable because with different language order on number of arguments will change and that is compile-time thing.{}
in other context may contain width specifier because we trying to format all numbers based on.. e.g. Excel table comun's width. So even that becomes flexible. – Guisestd::wformat_string
is provided at compile-time and can be saved as part of type information. I can show you how to avoidvformat
and useformat
instead. But that requires another discussion thread. – Ethno