There are three ways I have identified to solve the problem with operator<<
.
The first way is to provide an operator<<
for your type. This is needed because when boost_check_equal
fails, it also logs the failure by calling operator<<
with the objects. See the verbose addendum after the break to see how this is actually accomplished. It's harder than it might seem.
The second way is to not do the logging I just mentioned. You can do this by #definine
ing BOOST_TEST_DONT_PRINT_LOG_VALUE
. To disable logging for just one test, you might surround the test in question with this #define
, then immediately #undef
it:
#define BOOST_TEST_DONT_PRINT_LOG_VALUE
BOOST_CHECK_EQUAL (first, second);
#undef BOOST_TEST_DONT_PRINT_LOG_VALUE
The third way is to sidestep the need for an operator<<
that works with your type by not comparing one item to another, but just checking a bool:
BOOST_CHECK (first == second);
Select your preferred method.
My preference is the first, but implementing that is suprisingly challenging. If you simply define an operator<<
in global scope, it won't work. I think the reason for this is because of a problem with name resolution. One popular suggestion to fix this is to put the operator<<
in the std
namespace. This works, at least in practice on some compilers, but I don't like it because the Standard prohibits adding anything to the std
namespace.
A better method I found is to implement a custom print_log_value
class template specialization for your type. print_log_value
is a class template useb by the Boost.Test internals to actually call the correct operator<<
for the specified type. It delegates to an operator<<
to do the heavy lifting. Specializing print_log_value
for your custom types is officially supported by Boost [citation needed], and is accomplished thusly.
Assuming your type is called Timestamp
(it is in my code), first define a global free operator<<
for Timestamp
:
static inline std::ostream& operator<< (std::ostream& os, const Mdi::Timestamp& ts)
{
os << "Timestamp";
return os;
}
...and then provide the print_log_value
specialization for it, delegating to the operator<<
you just defined:
namespace boost { namespace test_tools {
template<>
struct print_log_value<Mdi::Timestamp > {
void operator()( std::ostream& os,
Mdi::Timestamp const& ts)
{
::operator<<(os,ts);
}
};
}}