Конвенция о печати контейнеров STL для испытаний - PullRequest
4 голосов
/ 21 апреля 2020

Я пишу тесты для утверждения с использованием превосходной библиотеки ApprovalTests. cpp. Эта библиотека автоматизирует генерацию «снимков» результатов из функции. Снимки генерируются в результате сериализации результатов типа T в файл с использованием ostream& operator<< (T val).

Этот оператор всегда был соглашением C ++ для форматирования некоторого значения в текстовое представление. Хотя примитивные типы поддерживают этот оператор, и вы можете написать свою собственную реализацию для пользовательских типов, стандартная реализация для контейнеров STL, таких как std::vector.

, отсутствует. Вы можете реализовать свою собственную, даже используя другие библиотеки, такие как fmt или pprint. Вот несколько примеров с похожими результатами. Я использую тип c тип STREAM в качестве параметра вместо конкретного типа ostream в качестве , рекомендованного ApprovalTests. cpp, но идея не меняется.

для l oop

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

Pretty print

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. Это может привести к поломке другого кода, где, например, тот же оператор был перегружен для вектора.

В Rust вы можете просто добавить #[Debug] поверх struct, который вы хотите отформатировать в текст, и он может быть автоматически преобразован в текстовое представление, или реализовать черту самостоятельно, если вам нужно неканоническое представление. Ответственность за определение реализации Debug лежит на авторе структуры. Вот почему каждый контейнер в стандартной библиотеке Rust имеет свою собственную реализацию Debug.

Я спрашиваю, существует ли какое-либо соглашение в C ++ или есть какое-то подобное предложение для стандарта . Это может быть полезно для проверочных тестов, как в моем случае, но также для регистрации или отладки (отладчик может использовать этот форматер для отображения значения переменной для пользователя).

1 Ответ

3 голосов
/ 22 апреля 2020

Мне не известны какие-либо соглашения или стандартные предложения по печати контейнеров. Однако библиотека {fmt} может печатать все, что угодно для диапазона и кортежа: https://fmt.dev/latest/api.html#ranges -and-tuple-formatting , чтобы вы могли интегрировать ее с ApprovalTests и избежать определения вставки в поток. сами операторы.

Отказ от ответственности : я являюсь автором {fmt}.

...