7

当尝试执行 BOOST_CHECK_EQUAL(pair, pair) 时,gcc 没有找到 pair 的流运算符,尽管声明了它。有趣的是 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);
}

这不会与错误一起编译:

...  instantiated from here
../boost-atp/release/include/boost/test/test_tools.hpp:326:9: error: no match for ‘operator<<’ in ‘ostr << t’
4

3 回答 3

12

Remus 的回答operator<<一样,在C++ 14 草案(N4296 部分:17.6.4.2.1)中未定义行为。Boost提供了一个钩子(这个答案使用),你可以写:std

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是一个模板,所以如果你没有声明一个模板化的值pair<T,U>,你将需要编写如下内容:

template<>
struct print_log_value<MyType>{ /* implementation here*/ };

编辑

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

namespace boost
{
    namespace test_tools
    {
        namespace tt_detail
        {
于 2015-11-27T22:27:03.083 回答
10

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

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

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

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

于 2012-06-11T07:45:03.037 回答
0

我一直在寻找类似的东西,一种自定义输出字符串以十六进制打印整数的方法。将运算符注入 std 命名空间会起作用,但我测试中的每个 BOOST_CHECK 都将以十六进制打印。

所以我在 boost 命名空间中注入了一些自定义运算符,我可以用一些全局布尔值来控制它们。

在这里查看我的答案boost-check-fails-to-compile-operator-for-custom-types

于 2014-02-22T00:24:57.427 回答