Boost.Test output_test_stream因模板化输出运算符而失败

时间:2010-07-06 10:23:40

标签: c++ unit-testing templates boost

我有一个班级:

class foo {
private:
    std::string data;
public:
    foo &append(const char* str, size_t n) { data.append(str,n); }

    // for debug output
    template <typename T>
    friend T& operator<< (T &out, foo const &f);

    // some other stuff
};

template <typename T>
T& operator<< (T &out, foo const &f) {
    return out << f.data;
}

我希望这适用于提供<<运算符的任何类。

这适用于std::cout,如:

std::cout << fooObject;

但以下失败:

BOOST_AUTO_TEST_CASE( foo_append_and_output_operator )
{
    // fooObject is accessable here
    const char* str = "hello";
    fooObject.append(str, strlen(str));

    output_test_stream output;
    output << fooObject;

    BOOST_CHECK( output.is_equal(str) );
}

g++告诉我:

In function ‘T& operator<<(T&, const foo&) 
    [with T = boost::test_tools::output_test_stream]’:
error: invalid initialization of reference of type
    ‘boost::test_tools::output_test_stream&’ from expression of type
    ‘std::basic_ostream<char, std::char_traits<char> >’

发生了什么事?

我在Ubuntu 8.04上使用Boost 1.34.1

3 个答案:

答案 0 :(得分:3)

您可能已经知道,但使用output_test_stream作为std::ostream有效:

class foo {
    // [...]
    friend
    std::ostream& operator<< ( std::ostream &os, const foo &f );
};

std::ostream& operator<< ( std::ostream &os, const foo &f ) {
    return os << f.data;
}

答案 1 :(得分:3)

所以我想我有一个解释,但还没有解决方案。 output_test_stream通过继承wrap_stringstream来实现其流功能。这个插入操作符是一个免费的函数模板,如下所示:

template <typename CharT, typename T>
inline basic_wrap_stringstream<CharT>&
operator<<( basic_wrap_stringstream<CharT>& targ, T const& t )
{
    targ.stream() << t;
    return targ;
}

// ... further down in the same header

typedef basic_wrap_stringstream<char>       wrap_stringstream;

使用output_test_stream作为流类型调用运算符,这使得它成为返回类型。然后,您的运算符调用上面的运算符,并传播返回值。但是,上述运算符的返回值是运算符的返回类型的超类。当编译器尝试创建您想要返回的引用时,它会发生阻塞,因为它无法从对超类的引用初始化对子类的引用,即使它们都引用同一个对象。这有什么意义吗?

答案 2 :(得分:0)

这是一个错字吗?你写了

foo.append(str, strlen(str));

但是foo是类的名称而不是对象。