In C++20 - how do you make a user-defined type compatible with std::format
?
For example, let's say I have a type called Point
:
struct Point {
int x;
int y;
};
with its operator<<
defined:
inline std::ostream&
operator<<(std::ostream& o, Point pt)
{ return o << "[" << pt.x << << ", " << pt.y << "]"; }
then will the following program output Hello [3, 4]!
?
int main() {
Point pt{3,4};
std::cout << std::format("Hello {}!\n", pt);
}
If yes - why and how?
If no - what do I have to add to the definition of Point
to to make it work?
std::format
doesn't support operator<<
, you need to provide a formatter
specialization for your type (Point
) instead. The easiest way to do it is by reusing one of existing formatters, e.g. std::formatter<std::string>
:
template <>
struct std::formatter<Point> : std::formatter<std::string> {
auto format(Point p, format_context& ctx) const {
return formatter<string>::format(
std::format("[{}, {}]", p.x, p.y), ctx);
}
};
This will give you all format specifications supported by std::string
out of the box. Here is an example of formatting Point
with center alignment padded with '~' to 10 characters:
auto s = std::format("{:~^10}", Point{1, 2});
// s == "~~[1, 2]~~"
which is nontrivial to achieve with iostreams.