使用 std::format 与具有 operator<< 的类型

6
使用 fmt 库,您可以轻松格式化定义了 operator<< 的类型。 正如在这里解释的那样,您只需添加一行代码即可扩展 ostream_formatter

template <> struct fmt::formatter<Foo> : ostream_formatter {};

现在你可以这样做:

fmt::format("Foo is {}", Foo());

通过 std::format() 可以实现类似的事情吗?我有一些已经定义了operator<<的类型,因此我想开始使用它们与std::format()一起。

如果我尝试编写自己的格式化程序,我不知道如何从format()成员函数中的参数中获取ostream

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;
        ...
    }
};

直接编写格式化程序是否比依赖operator<<更好?


我认为您需要创建自己的 std::stream_buf,并从上下文中向迭代器编写数据。 - Alan Birtles
你可以查看 fmtlib 的实现,尽管它使用了一些标准库中没有的东西(例如 basic_memory_buffer)。如果你不担心性能问题,我想你可以简单地使用 stringstream 然后返回 std::format("{}", ss.str()) - Holt
еҪ“жӮЁеҸҜд»ҘзӣҙжҺҘдҪҝз”Ёss.str()ж—¶пјҢдҪҝз”Ёstd::format("{}", ss.str())жІЎжңүд»»дҪ•ж„Ҹд№үгҖӮ - Remy Lebeau
1个回答

4
你可以使用字符串流将值输出,然后将其内容作为结果检索,例如:
#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>;

那么

template <> struct std::formatter<ClassWithOstream> : ostream_formatter {};

需要注意以下几点:

  1. 对于 MSVC >= 16.11,此代码可以直接使用。对于早于 16.11 的 MSVC 版本,需要移除 format 成员函数上的 const 限定符,前提是该版本支持 std::format
  2. 此代码适用于 libc++(15 版或更高版本),但需要将 ss.view() 替换为 ss.str()
  3. 由于尚未支持 <format>,因此此代码可能无法在 libstdc++ 上运行。

这部分内容有些是从{fmt}实现中改编而来,不同的是{fmt}使用自己的basic_memory_bufferstd::basic_stringstream不同,它使用了std::basic_ostream


1
我正在使用clang和libc++(最新HEAD版本),但它仍然没有ss.view() :(。但其余部分都可以正常工作。它确实有formatter。我将使用ss.str()。由于我在这里并不过于关注性能 - 更多的是快速让事情正常工作 - 所以现在对我来说这样做是可以接受的。 - Rob N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接