With the fmt library, you can easily format types that have operator<< defined. As explained here, you extend ostream_formatter with one line of code:
template <> struct fmt::formatter<Foo> : ostream_formatter {};
Now you can do this:
fmt::format("Foo is {}", Foo());
Is a similar thing possible with std::format()? I have types for which operator<< is already defined, so I'd like to start using them with std::format().
If I try to write my own formatter, I don't see how I can get an ostream from the arguments in the format() member function.
template <typename T>
struct ostream_formatter : std::formatter<T> {
constexpr auto parse(std::format_parse_context& ctx) {
return ctx.begin();
}
auto format(const T& obj, auto& ctx) const {
ostream out = ???;
out << obj;
...
}
};
Is it better to write the formatters directly and not depend on operator<<?
You can use a string stream to output the value to and then retrieve its content as the result, e.g.
#include <format>
#include <string_view>
#include <sstream>
template <typename Char>
struct basic_ostream_formatter : std::formatter<std::basic_string_view<Char>, Char> {
template <typename T, typename OutputIt>
auto format(const T& value, std::basic_format_context<OutputIt, Char>& ctx) const
-> OutputIt {
std::basic_stringstream<Char> ss;
ss << value;
return std::formatter<std::basic_string_view<Char>, Char>::format(
ss.view(), ctx);
}
};
using ostream_formatter = basic_ostream_formatter<char>;
Then
template <> struct std::formatter<ClassWithOstream> : ostream_formatter {};
With a few precautions
std::format, you need to remove the const-qualifier on the format member function.ss.view() with ss.str().<format> is not supported (yet).Some of this is adapted from {fmt} implementation except {fmt} uses its own basic_memory_buffer with a std::basic_ostream instead of std::basic_stringstream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With