印刷STL容器用于认可测试的约定

Convention on printing STL containers for approval tests

我正在使用出色的 ApprovalTests.cpp 库编写批准测试。该库自动从函数生成 "snapshots" 结果。快照是使用 ostream& operator<< (T val).

T 类型的结果序列化到文件中生成的

此运算符一直是将某些值格式化为文本表示形式的 C++ 约定。虽然原始类型支持此运算符,并且您可以为自定义类型编写自己的实现,但对于像 std::vector.

这样的 STL 容器,没有标准的实现

您可以自己实现,甚至可以使用 fmtpprint 等其他库。下面是一些具有类似输出的示例。我使用通用类型 STREAM 作为参数而不是具体类型 ostream 作为 recommended by ApprovalTests.cpp 但想法没有改变。

for循环

template <typename STREAM, typename T> STREAM& operator<<(STREAM& os, const std::vector<T>& vec) {
  os << "[";
  for (const auto& x : vec) {
    os << x << ", ";
  }
  os << "]";
  return os;
}

ostream_iterator

template <typename T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  using namespace std;
  os << "[";
  copy(v.begin(), v.end(), ostream_iterator<T>(os, ", "));
  os << "]";
  return os;
}

fmt

https://github.com/fmtlib/fmt

template <typename STREAM, typename T> STREAM& operator<<(STREAM& os, const std::vector<T>& vec) {
  fmt::print(os, "[{}]", fmt::join(vec, ", "));
  return os;
}

<fmt/ranges.h header:

template <typename STREAM, typename T> STREAM& operator<<(STREAM& os, const std::vector<T>& vec) {
  fmt::print(os, "{}", vec);
  return os;
}

印刷精美

https://github.com/p-ranav/pprint

template <typename STREAM, typename T> STREAM& operator<<(STREAM& os, const std::vector<T>& vec) {
  pprint::PrettyPrinter printer{os};
  printer.print(vec);
  return os;
}

cxx-prettyprint

只需包含 prettyprint.hpp,它适用于 STL 容器。

这似乎是最简单的解决方案,但与其他解决方案存在相同的问题,可能会破坏其他代码。

约定?

在使用了一些 Rust 之后,我发现为每个 C++ STL 容器执行此操作很乏味。这样做可能会破坏其他代码,例如,相同的运算符已为 vector 重载。

在 Rust 中,您可以在要格式化为文本的 struct 上添加 #[Debug],它可以自动转换为文本表示,或者如果您需要一些 non-canonical表示。结构作者有责任定义其 Debug 实现。这就是为什么 Rust 标准库中的每个容器都有自己的 Debug 实现。

我想问的是 C++ 中是否存在某些约定,或者是否有一些类似的标准提案。它可能对批准测试很有用,就像在我的例子中一样,但对日志记录或调试也很有用(调试器可以使用此格式化程序向用户显示变量值)。

我不知道关于打印容器的任何约定或标准提案。然而 {fmt} library can print anything range- and tuple-like: https://fmt.dev/latest/api.html#ranges-and-tuple-formatting 所以你可以将它与 ApprovalTests 集成并避免自己定义 ostream 插入运算符。

免责声明:我是{fmt}的作者。