如何制作 boost.Test log/print 标准类型
How to make boost.Test log/print std types
#include <boost/test/included/unit_test.hpp>
BOOST_AUTO_TEST_CASE(test1)
{
std::optional<int> opt1(10);
BOOST_TEST(t == 11);
std::optional<long> opt2(11);
BOOST_CHECK_EQUAL(opt1, opt2);
}
有什么方法可以使 boost 测试打印(在代码中:BOOST_TEST)std
类型?重载 operator<<
必须在命名空间 std
中才能被 ADL 找到,并且禁止扩展 std
。 boost's documentation 中唯一提到的是关于 UDT 的解决方案也依赖于 ADL,因为它强调在与 UDT 相同的命名空间中添加自定义函数 boost_test_print_type
。
关于建议的副本
我不确定。一式两份提出的薄包装纸将如何工作?这是否意味着我必须在每个断言之前转换为每个测试用例中的包装器,而不是直接使用标准类型(可选)?如果是这样,那不是我要找的,也不是我想要的!
这是一个基于包装器模板的解决方案。我认为它远非理想,但它应该按预期工作。
template <class T>
struct PrintableOpt {
std::optional<T> value;
};
必要的运算符重载是
template <class T>
std::ostream& operator << (std::ostream& os, const PrintableOpt<T>& opt)
{
if (opt.value)
return os << *opt.value;
else
return os << "std::nullopt";
}
template <class T, class U>
bool operator == (const PrintableOpt<T>& lhs, const PrintableOpt<U>& rhs)
{
return lhs.value && rhs.value && *lhs.value == *rhs.value;
}
template <class T, class U>
bool operator != (const PrintableOpt<T>& lhs, const PrintableOpt<U>& rhs)
{
return !(lhs == rhs);
}
为了方便起见,这里有两个帮助函数来构造包装器实例:
template <class T>
auto printable(T&& opt)
{
return PrintableOpt<T>{std::forward<T>(opt)};
}
template <class T>
auto printable(std::optional<T>& opt)
{
return PrintableOpt<T>{opt};
}
测试现在看起来像这样:
BOOST_AUTO_TEST_CASE(test1)
{
std::optional<int> opt1(10);
BOOST_TEST(printable(opt1) == printable(11));
std::optional<long> opt2(11);
BOOST_CHECK_EQUAL(printable(opt1), printable(opt2));
}
#include <boost/test/included/unit_test.hpp>
BOOST_AUTO_TEST_CASE(test1)
{
std::optional<int> opt1(10);
BOOST_TEST(t == 11);
std::optional<long> opt2(11);
BOOST_CHECK_EQUAL(opt1, opt2);
}
有什么方法可以使 boost 测试打印(在代码中:BOOST_TEST)std
类型?重载 operator<<
必须在命名空间 std
中才能被 ADL 找到,并且禁止扩展 std
。 boost's documentation 中唯一提到的是关于 UDT 的解决方案也依赖于 ADL,因为它强调在与 UDT 相同的命名空间中添加自定义函数 boost_test_print_type
。
关于建议的副本
我不确定。一式两份提出的薄包装纸将如何工作?这是否意味着我必须在每个断言之前转换为每个测试用例中的包装器,而不是直接使用标准类型(可选)?如果是这样,那不是我要找的,也不是我想要的!
这是一个基于包装器模板的解决方案。我认为它远非理想,但它应该按预期工作。
template <class T>
struct PrintableOpt {
std::optional<T> value;
};
必要的运算符重载是
template <class T>
std::ostream& operator << (std::ostream& os, const PrintableOpt<T>& opt)
{
if (opt.value)
return os << *opt.value;
else
return os << "std::nullopt";
}
template <class T, class U>
bool operator == (const PrintableOpt<T>& lhs, const PrintableOpt<U>& rhs)
{
return lhs.value && rhs.value && *lhs.value == *rhs.value;
}
template <class T, class U>
bool operator != (const PrintableOpt<T>& lhs, const PrintableOpt<U>& rhs)
{
return !(lhs == rhs);
}
为了方便起见,这里有两个帮助函数来构造包装器实例:
template <class T>
auto printable(T&& opt)
{
return PrintableOpt<T>{std::forward<T>(opt)};
}
template <class T>
auto printable(std::optional<T>& opt)
{
return PrintableOpt<T>{opt};
}
测试现在看起来像这样:
BOOST_AUTO_TEST_CASE(test1)
{
std::optional<int> opt1(10);
BOOST_TEST(printable(opt1) == printable(11));
std::optional<long> opt2(11);
BOOST_CHECK_EQUAL(printable(opt1), printable(opt2));
}