将 std::format 与具有运算符 << 的类型一起使用

Rob*_*b N 7 c++ c++20 fmt

使用fmt库,您可以轻松格式化已定义的类型operator<<。正如这里所解释的,您可以ostream_formatter使用一行代码进行扩展:

template <> struct fmt::formatter<Foo> : ostream_formatter {};
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

fmt::format("Foo is {}", Foo());
Run Code Online (Sandbox Code Playgroud)

类似的事情可能吗std::format()?我有已经定义的类型operator<<,所以我想开始将它们与std::format().

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

template <> struct fmt::formatter<Foo> : ostream_formatter {};
Run Code Online (Sandbox Code Playgroud)

直接编写格式化程序而不依赖于 是否更好operator<<

Hol*_*olt 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>;
Run Code Online (Sandbox Code Playgroud)

然后

template <> struct std::formatter<ClassWithOstream> : ostream_formatter {};
Run Code Online (Sandbox Code Playgroud)

采取一些预防措施

  1. 这在 MSVC >= 16.11 中按原样工作。对于 16.11 之前支持的 MSVC std::format,您需要删除成员函数const上的 - 限定符format
  2. 这适用于 libc++(版本 15 或更高版本),但您需要替换ss.view()ss.str().
  3. 这可能不适用于 libstdc++,因为<format>尚不支持。

其中一些是根据{fmt} 实现改编的,除了 {fmt} 使用它自己的basic_memory_bufferastd::basic_ostream而不是std::basic_stringstream