开发者

Boost.Test output_test_stream fails with templated output operator

开发者 https://www.devze.com 2023-01-05 16:41 出处:网络
I have a class: class foo { private: std::string data; public: foo &append(const char* str, size_t n) { data.append(str,n); }

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消