When attempting to do a BOOST_CHECK_EQUAL(pair, pair), gcc doesnt find the stream operator for pair, inspite of declaring it. The funny thing is that std::out finds the operator.
ostream& operator<<(ostream& s, const pair<int,int>& p) {
s << '<' << p.first << ',' << p.second << '>';
return s;
}
BOOST_AUTO_TEST_CASE(works)
{
pair<int,int> expected(5, 5);
pair<int,int> actual (5, 5);
std::cout << expected << std::endl;
std::cout << actual << std::endl;
BOOST_CHECK(actual == expected);
}
BOOST_AUTO_TEST_CASE(no_work)
{
pair<int,int> expected(5, 5);
pair<int,int> actual (5, 5);
BOOST_CHECK_EQUAL(actual, expected);
}
This doesnt compile with the error:
... instantiated from here
../boost-atp/release/include/boost/test/test_tools.hpp:326:9: error: no match for ‘operator<<’ in ‘ostr << t’
Putting operator<<
in std
like Remus's answer is undefined behavior in the C++ 14 draft (N4296 section:17.6.4.2.1). Boost provides a hook (used by this answer) and you can write:
namespace boost
{
namespace test_tools
{
template<typename T,typename U>
struct print_log_value<std::pair<T, U> >
{
void operator()(std::ostream& os, std::pair<T, U> const& pr)
{
os << "<" << std::get<0>(pr) << "," << std::get<1>(pr) << ">";
}
};
}
}
print_log_value
is a template so if you are not declaring a templated value like pair<T,U>
, you will need to write something like:
template<>
struct print_log_value<MyType>{ /* implementation here*/ };
Edit
If you are using boost 1.59 or later you need to use namespace boost::test_tools::tt_detail
instead. That is, the code needs to start:
namespace boost
{
namespace test_tools
{
namespace tt_detail
{
Try putting the operator itself in the std namespace:
namespace std
{
ostream& operator<<(ostream& s, const pair<int,int>& p) {
s << '<' << p.first << ',' << p.second << '>';
return s;
}
}
Update: perhaps this is why the ADL fails (at least on llvm):
Just like before, unqualified lookup didn't find any declarations with the name
operator<<
. Unlike before, the argument types both contain class types: one of them is an instance of the class template typestd::basic_ostream
, and the other is the typens::Data
that we declared above. Therefore, ADL will look in the namespacesstd
andns
for anoperator<<
. Since one of the argument types was still dependent during the template definition, ADL isn't done until the template is instantiated during Use, which means that theoperator<<
we want it to find has already been declared. Unfortunately, it was declared in the global namespace, not in either of the namespaces that ADL will look in!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With