如何为已定义operator<<的类型实现std::format支持?
在std::format中适配已有operator<<的类型
首先明确:std::format没有内置类似fmt库ostream_formatter的直接继承方案,但你可以自己实现一个适配模板,复用已有的operator<<来支持格式化。
实现适配的formatter模板
你不需要从format参数里获取ostream——std::format的格式化上下文提供的是输出迭代器(通过ctx.out()获取),而非直接的ostream。我们可以借助std::ostringstream作为中间缓冲区,把operator<<的输出转写到这个迭代器里:
#include <format> #include <sstream> template <typename T> struct ostream_formatter { // 解析格式说明符(这里默认不处理任何格式,和fmt的ostream_formatter行为一致) constexpr auto parse(std::format_parse_context& ctx) const { // 如果需要支持格式说明符,可以在这里扩展逻辑 return ctx.begin(); } auto format(const T& obj, std::format_context& ctx) const { std::ostringstream oss; oss << obj; // 将字符串流的内容写入输出迭代器 return std::ranges::copy(oss.str(), ctx.out()).out; } }; // 针对你的类型Foo特化formatter template <> struct std::formatter<Foo> : ostream_formatter<Foo> {};
这样之后,你就可以像用fmt一样,直接用std::format("{}", Foo{})来格式化Foo类型了。
要不要直接写formatter而非依赖operator<<?
分两种情况看:
- 如果已经有成熟的
operator<<实现,复用它是最快捷的方式,不用重复编写格式化逻辑,减少代码冗余。 - 如果追求极致性能,直接编写formatter会更优——因为上面的适配方案用到了中间的
std::ostringstream,会有额外的内存分配和拷贝开销。直接写formatter的话,可以直接将内容写入ctx.out()的迭代器,跳过中间缓冲区。
内容的提问来源于stack exchange,提问作者Rob N
相关产品推荐
相关产品推荐

