问题
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’
回答1:
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
{
回答2:
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!
回答3:
I was looking for something similar, a way to customize the output string to print integers in hex. Injecting an operator into the std namespace would work, but every BOOST_CHECK in my test would be printed in hex.
So I injected some custom operators in the boost namespace that I could control with some global bools.
See my answer here boost-check-fails-to-compile-operator-for-custom-types.
来源:https://stackoverflow.com/questions/10976130/boost-check-equal-with-pairint-int-and-custom-operator