使用 libfmt 打印或格式化自定义类型的简单方法是什么?

问题描述 投票:0回答:3

假设我定义了某种类型,例如

struct Foo { int a; float b; };

如果我想将其流式传输到ostream,我会编写一个

operator<<
函数,例如:

std::ostream& operator<<(std::ostream& os, const Foo& foo)
{
  return os << '(' << a << ',' << b << ')';
}

现在我想做同样的事情,但是在

fmt::format()
fmt::print()
通话中。如果我写:

fmt::print("{}\n", foo);

我会得到一堆错误,最后是这样的:

/path/to/fmt/core.h:1073:9: error: static assertion failed: Cannot format argument. 
To make type T formattable provide a formatter<T> specialization:
https://fmt.dev/latest/api.html#formatting-user-defined-types

好吧,所以,我去那里,我看到了一堆例子,其中第一个已经有点复杂了。为了实现我想要的目标,我可以写的最简单的东西是什么?

c++ formatting fmt
3个回答
7
投票

为了简化示例,我们假设您只愿意接受

{}
格式说明符,而没有任何其他字符串控制打印的外观。在这种情况下,你可以这样写:

template <> class fmt::formatter<Foo> {
public:
  constexpr auto parse (format_parse_context& ctx) { return ctx.begin(); }
  template <typename Context>
  constexpr auto format (Foo const& foo, Context& ctx) const {
      return format_to(ctx.out(), "({}, {})", foo.a, foo.b);  // --== KEY LINE ==--
  }
};

就是这样。有点巴洛克式,你无法删除第一个方法(为什么?...),但也没有那么糟糕。从此处复制粘贴此片段;将

Foo
替换为您的类型;并在关键行上重写实际的格式化命令。

完整示例程序:

#include <fmt/format.h>

struct Foo { int a; float b; };

template <>
class fmt::formatter<Foo> {
public:
  constexpr auto parse (format_parse_context& ctx) { return ctx.begin(); }
  template <typename Context>
  constexpr auto format (Foo const& foo, Context& ctx) const {
      return format_to(ctx.out(), "({},{})", foo.a, foo.b);
  }
};

int main () {
  Foo foo {123, 4.56};
  fmt::print("{}\n", foo);
}

看到它正在运行 GodBolt


1
投票

这也有效:

#include "spdlog/fmt/ostr.h"

struct Foo { int a; float b; };

std::ostream& operator<<(std::ostream& os, const Foo& foo) {
    return os << "(" << foo.a << "," << foo.b << ")";
}

int main () {
    Foo foo {123, 4.56};
    fmt::print("{}\n", foo);
}

上帝闪电:https://godbolt.org/z/vrEWGP1fn


0
投票

我用一个简单的解决方案让它工作

struct Custom {
    std::string format() { return "my-custom-data"; }
};

template <> struct fmt::formatter<Custom> : formatter<std::string> {
  auto format(Custom const &c, format_context& ctx) {
    return formatter<std::string>::format(c.format(), ctx);
  }
};

感谢https://stackoverflow.com/a/58552038/2258077

© www.soinside.com 2019 - 2024. All rights reserved.