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::Datathat we declared above. Therefore, ADL will look in the namespacesstdandnsfor 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