std::format 个用户定义类型?
std::format of user-defined types?
在 C++20 中 - 如何使用户定义的类型与 std::format
兼容?
例如,假设我有一个名为 Point
:
的类型
struct Point {
int x;
int y;
};
其 operator<<
定义:
inline std::ostream&
operator<<(std::ostream& o, Point pt)
{ return o << "[" << pt.x << << ", " << pt.y << "]"; }
那么下面的程序会输出Hello [3, 4]!
吗?
int main() {
Point pt{3,4};
std::cout << std::format("Hello {}!\n", pt);
}
如果是 - 为什么以及如何?
如果不是 - 我必须在 Point
的定义中添加什么才能使其工作?
你必须std::formatter
适合你的类型。
namespace std
{
template<class CharT>
struct formatter<Point, CharT>
{
template <typename FormatParseContext>
auto parse(FormatParseContext& pc)
{
// parse formatter args like padding, precision if you support it
return pc.end(); // returns the iterator to the last parsed character in the format string, in this case we just swallow everything
}
template<typename FormatContext>
auto format(Point p, FormatContext& fc)
{
return std::format_to(fc.out(), "[{}, {}]", p.x, p.y);
}
};
}
我不认为 ostream 运算符会起作用,但我没有任何来源来支持这一说法。
std::format
不支持 operator<<
,您需要为您的类型 (Point
) 提供 formatter
专业化。最简单的方法是重用现有的格式化程序之一,例如std::formatter<std::string>
:
template <>
struct std::formatter<Point> : std::formatter<std::string> {
auto format(Point p, format_context& ctx) {
return formatter<string>::format(
std::format("[{}, {}]", p.x, p.y), ctx);
}
};
这将为您提供开箱即用的 std::string
支持的所有格式规范。下面是一个格式化 Point
的例子,中心对齐用 '~' 填充到 10 个字符:
auto s = std::format("{:~^10}", Point{1, 2});
// s == "~~[1, 2]~~"
使用 iostream 实现这一点很重要。
在 C++20 中 - 如何使用户定义的类型与 std::format
兼容?
例如,假设我有一个名为 Point
:
struct Point {
int x;
int y;
};
其 operator<<
定义:
inline std::ostream&
operator<<(std::ostream& o, Point pt)
{ return o << "[" << pt.x << << ", " << pt.y << "]"; }
那么下面的程序会输出Hello [3, 4]!
吗?
int main() {
Point pt{3,4};
std::cout << std::format("Hello {}!\n", pt);
}
如果是 - 为什么以及如何?
如果不是 - 我必须在 Point
的定义中添加什么才能使其工作?
你必须std::formatter
适合你的类型。
namespace std
{
template<class CharT>
struct formatter<Point, CharT>
{
template <typename FormatParseContext>
auto parse(FormatParseContext& pc)
{
// parse formatter args like padding, precision if you support it
return pc.end(); // returns the iterator to the last parsed character in the format string, in this case we just swallow everything
}
template<typename FormatContext>
auto format(Point p, FormatContext& fc)
{
return std::format_to(fc.out(), "[{}, {}]", p.x, p.y);
}
};
}
我不认为 ostream 运算符会起作用,但我没有任何来源来支持这一说法。
std::format
不支持 operator<<
,您需要为您的类型 (Point
) 提供 formatter
专业化。最简单的方法是重用现有的格式化程序之一,例如std::formatter<std::string>
:
template <>
struct std::formatter<Point> : std::formatter<std::string> {
auto format(Point p, format_context& ctx) {
return formatter<string>::format(
std::format("[{}, {}]", p.x, p.y), ctx);
}
};
这将为您提供开箱即用的 std::string
支持的所有格式规范。下面是一个格式化 Point
的例子,中心对齐用 '~' 填充到 10 个字符:
auto s = std::format("{:~^10}", Point{1, 2});
// s == "~~[1, 2]~~"
使用 iostream 实现这一点很重要。