Open utterances-bot opened 2 years ago
My company has been using fmtlib for a couple of years now. The biggest hurdle has been adoption from our math majors (which we have a lot of, being a simulation program). They really want to put an indicator in the {} that says the type. I can actually understand this for them they want to know the type for certain and then have strong checking.
One big problem with this is that, if you specify a type with a floating point number, like {:f}, there is no way to get the minimum size for guaranteed double-->string-->double exactness. Specifying any options at all gives you a specified precision or format type.
If the result of std::format is to a stream (which is pretty normal), then you could combine stream insertion with std::format for a custom type without getting involved with custom formatters. eg.
#include <iostream>
#include <format>
#include <iterator>
using fmtstrm = std::ostream_iterator<char>;
struct myStrt {
std::string s;
int i {};
double d {};
};
std::ostream& operator<<(std::ostream& os, const myStrt& strt) {
std::format_to(fmtstrm(os), "{:-^10}:{:0>10}:{:10.3}", strt.s, strt.i, strt.d);
return os;
}
int main() {
myStrt st { "hello", 34, 6.78 };
std::cout << st << '\n';
}
Which displays: --hello---:0000000034: 6.78
@RobL371
Can't you do something like:
std::format("{:{}.{}f}", 3.1415926539, 10, 5);
where 10 is the width and 5 is the precision. The width can be a calculated value etc.
@2kaud
No, that doesn't work. If you just use {}, then you get a guarantee: The resulting string will be the shortest possible string where a conversion from string back to double exactly matches the original. There is no way to get that guarantee if you use any other options.
Ah yes. I see. If a type is specified, then if precision is not 6 then a precision has to be specified. Only {} doesn't require a precision if 6 is not required. This is due to std:::format using std::to_chars() for the conversion. Only {} calls std::to_chars() without specifying a precision.
You could write your own formatter as per above with a parse() for say type D (d is already used for decimal) that does the same as {}
As a 'proof of concept', have a look at https://godbolt.org/z/f7M74EoqG
Any specified format specification is ignored - effectively giving {}
Yep, that's a good example. The only issue is that we shouldn't need to do that. :)
For MSVC v17.5, the format() member function in a user defined std::formatter specialization does not have to be const, but for gcc v13.1 and clang trunk (for v17, as of today), the format() function must be const.
For latest MSVC in Compiler Explorer (GodBolt) => custom formatter is not working! I also tried it in the latest Visual Studio 2022 Preview Edition. Could anyone help?
See https://godbolt.org/z/8Mc8nqfdx for an example with std::array. GodBolt doesn't execute MSVC code, but it does compile.
It seems that, for clang's STL at least, the format
function must be a template and can't just take std::format_context
as argument (see https://github.com/llvm/llvm-project/issues/66466). I.e. one needs to write, for example,:
...
template<class FormatContext>
auto format(const MyCustomType& v, FormatContext& ctx) const {
return std::format_to(ctx.out(), "my custom value");
}
...
instead of just using std::format_context
directly:
...
auto format(const MyCustomType& v, std::format_context& ctx) const {
return std::format_to(ctx.out(), "my custom value");
}
...
See https://godbolt.org/z/67hcP66as which fails, as opposed to https://godbolt.org/z/5rrWobxP9, which succeeds.
It seems that, for clang's STL at least, the
format
function must be a template and can't just takestd::format_context
as argument (see llvm/llvm-project#66466). I.e. one needs to write, for example,:
I (the author of libc++'s format implementation) am confused about what the problem is.
https://godbolt.org/z/67hcP66as fails with a linker error since there is no main function.
https://godbolt.org/z/sbKzEYGdr renames testing
to main
and executes successfully.
If there is still an issue, could you file a bug-report for libc++? TIA.
Custom types and std::format from C++20 - C++ Stories
std::format is a large and powerful addition in C++20 that allows us to format text into strings efficiently. It adds Python-style formatting with safety and ease of use. This article will show you how to implement custom formatters that fit into this new std::format architecture. Quick Introduction to std::format Here’s the Hello World example:
https://www.cppstories.com/2022/custom-stdformat-cpp20/