I am trying to use c++20's std::format on msvc.
When I try to define a format for a custom type Person, I hope to be able to use the external std::format("{:x}{:*^10}", person)
in "{:x}{:*^10}"
is forwarded to std::formatter<Person>::fomat
and used directly in std::formatter<Person>::fomat
for example:
#include <format>
#include <iostream>
#include <string>
#include <string_view>
class Person {
public:
int age;
std::string name;
};
template <>
struct std::formatter<Person> : std::formatter<std::string> {
template <typename FormatContext>
auto format(const Person& p, FormatContext& ctx) {
// I hope that the "forwarded format" here is "{:x}{:*^10}" in the format information of ::std::format in main. \
This code is of course not runnable. I want to know How can I use an external format in formatter<Person>::foaramt like this
return format_to(ctx.out(),"forwarded format",p.age,p.name);
}
};
int main() {
Person person{ 30,"John Doe" };
std::cout << std::format("{:x}{:*^10}", p) << '\n';
return 0;
}
I hope to be able to use the forwarded formatting information "{:x}{:*^10}" directly in std::formatter::format,
Instead of changing std::foramt("{:x}{:*^10}",person)
to std::format("{:x}{:*^10}",person.age,person.name)
You can define a string_view
variable in std::formatter<Person>
to store formatting information.
Then, calculate the format string for members in the parse()
function and assign it to this variable, and use it in the format()
function.
(For simplicity, some compile-time checks inside the parse
function are omitted)
template <>
struct std::formatter<Person> {
std::string_view fmt_str; // formatting information
template<typename ParseContext>
constexpr auto parse(ParseContext& ctx) {
auto begin = ctx.begin(); // ctx is "x}{:*^10}"
auto it = std::formatter<int>{}.parse(ctx); // now, it point to "}{:*^10}"
it = std::ranges::find(it + 1, ctx.end(), ':'); // now, it point to ":*^10}"
ctx.advance_to(it + 1); // now, ctx is "*^10}"
it = std::formatter<std::string>{}.parse(ctx); // now, it point to "}"
fmt_str = {begin - 2, it + 1}; // now fmt_str is "{:x}{:*^10}"
return it;
}
template <typename FormatContext>
auto format(const Person& p, FormatContext& ctx) const {
return std::vformat_to(ctx.out(), fmt_str, std::make_format_args(p.age, p.name));
}
};