Boost.Test output_test_stream fails with templated output operator
I have a class:
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;
}
I want this to work with any class that provides the <<
operator.
This works fine with std::cout
as in:
std::cout << fooObject;
But the following fails:
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++
tells me that:
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> >’
What's going on?
I'm using Boost 1.34.1 on Ubuntu 8.04.
So I think I have an explanation, but no solution yet. output_test_stream
implements its stream functionality by subclassing wrap_stringstream
. The insertion-operator for this is a free function-template that looks like this:
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;
Your operator is called with output_test_stream
as the stream-type, and that makes this it's return-type. Your operator then calls the above operator, and just propagates the return value. The return value of the above operator however is a superclass of the returntype of your operator. When compiler tries to create the reference you want to return, it chokes, because it cannot initialize a reference to a subclass from a reference to a superclass, even if both refer to the same object. That make any sense?
You may know that already, but using output_test_stream
as an std::ostream
works:
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;
}
Is it a typo? You wrote
foo.append(str, strlen(str));
but foo
is the name of the class and not an object.
精彩评论