Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherit from std::ostringstream

In my project I use a class class called Message which inherits from std::ostringstream to print out human readable information of other class types.

So its << operator is overloaded several times taking my own class types which I want to print out.

class Message : public ostringstream
{
public:
    Message() {};
    virtual ~Message() {};

    Message& operator <<(const MyTypeA &a) { return *this << a.getStr(); };
    Message& operator <<(const MyTypeB &b) { return *this << b.identifier(); };
    Message& operator <<(const MyTypeC &c) { return *this << c.foo(); };

    // Pass everything unknown down to ostringstream, and always return a Message&
    template<class T>
    Message& operator <<(const T &t)
    {
        (std::ostringstream&)(*this) << t;
        return *this;
    }
};

Without the template

MyTypeA a,b;
Message m;
m << a << "-" << b;

the code would not compile, as (m << a << "-") would return a ostringstream& which would not be able to take 'b'. So I use the template to make sure to always return a Message&.

My Problem:

Message m;
m << "Hello, world" << std::endl;

generates a veeery long compiler error and I do not know why.

Here is a minimalistic "not" compilable example of my problem, and here is the corresponding compiler output.

like image 550
rralf Avatar asked Dec 11 '25 15:12

rralf


1 Answers

Do not derive from any of the stream classes to create a new stream! The only reason to derive from std::ostream or std::istream is to create a stream properly set up to use a suitable stream buffer. Instead of deriving from a stream, you should derive from std::streambuf to create a new source or destination. To create output operators for new types you'd overload operator<<() with std::ostream& as first argument and your custom type as second argument. Likewise with std::istream&.

BTW, the problem you encountered is because std::endl is a function template. Trying to pass a function template somewhere requires that the appropriate instantiation can be deduced. Since your output operators don't cover a suitable signature, the instantiation of std::endl can't be deduced. I could state what's needed but that would be pointless as it is the wrong way to go anyway.

like image 121
Dietmar Kühl Avatar answered Dec 15 '25 04:12

Dietmar Kühl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!