Я пишу тесты для утверждения с использованием превосходной библиотеки 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 ++ или есть какое-то подобное предложение для стандарта . Это может быть полезно для проверочных тестов, как в моем случае, но также для регистрации или отладки (отладчик может использовать этот форматер для отображения значения переменной для пользователя).