带有对<int,int>和自定义运算符<<的BOOST_CHECK_EQUAL

nis*_*tjr 7 c++ boost boost-test

当尝试执行BOOST_CHECK_EQUAL(对,对)时,gcc没有找到对的流操作符,尽管声明它.有趣的是std :: out找到了运营商.

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);
}
Run Code Online (Sandbox Code Playgroud)

这不会编译错误:

...  instantiated from here
../boost-atp/release/include/boost/test/test_tools.hpp:326:9: error: no match for ‘operator<<’ in ‘ostr << t’
Run Code Online (Sandbox Code Playgroud)

Epo*_*ous 10

operator<<stdRemus的答案是C++ 14草案(N4296部分:17.6.4.2.1)未定义的行为.Boost提供了一个钩子(由这个答案使用)你可以写:

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) << ">";
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

print_log_value是一个模板,所以如果你没有声明像这样的模板化值pair<T,U>,你需要写一些类似的东西:

template<>
struct print_log_value<MyType>{ /* implementation here*/ };
Run Code Online (Sandbox Code Playgroud)

编辑

如果您使用的是boost 1.59或更高版本,则需要使用命名空间boost::test_tools::tt_detail.也就是说,代码需要启动:

namespace boost
{
    namespace test_tools
    {
        namespace tt_detail
        {
Run Code Online (Sandbox Code Playgroud)


Rem*_*anu 9

尝试将运算符本身放在std命名空间中:

namespace std
{
  ostream& operator<<(ostream& s, const pair<int,int>& p) {
    s << '<' << p.first << ',' << p.second << '>';
    return s;
  }
}
Run Code Online (Sandbox Code Playgroud)

更新:也许这就是ADL失败的原因(至少在llvm上):

就像以前一样,不合格的查找没有找到任何带有名称的声明operator<<.与之前不同,参数类型都包含类类型:其中一个是类模板类型的实例, std::basic_ostream另一个是ns::Data我们在上面声明的类型.因此,ADL会看在命名空间stdns 一个operator<<.由于其中一个参数类型在模板定义期间仍然依赖于ADL,因此在使用期间实例化模板之前不会执行ADL,这意味着operator<<我们已经声明了要查找的模板.不幸的是,它是在全局命名空间中声明的,而不是在ADL将要查看的任一命名空间中声明的!