Question

I have a lot of logging functions, which right now accept an ostringstream&. My goal is to make them able to accept a stream written in one line, something like this:

MyPrint( ostringstream() << "hello!" << endl);

I cannot change the method prototype considerably since I have a lot of legacy code that must still work. I want to change it to ostream& because that is the return value type of <<. Right now the prototypes are of the form:

void MyPrint( <some parameters>, ostringstream& stream)

My suggested change after reading here c++ stringstream to ostream to string, is (lets ignore the other parameters):

void MyPrint(ostream& stream)
{
    stringstream ss;
    ss << stream.rdbuf();
    cout << "ss is:" << ss.str() << endl;
}

and the following line works:

MyPrint(stringstream().flush() << "hello world!" << endl);

but this prints a blank:

ostringstream oss;
oss << "hello world!" << endl;
MyPrint(oss);

(this would've actually worked with a stringstream for some reason)

The second form must work since this is how my legacy code is written.

Also if i could avoid having to write something inelegant like stringstream().flush() I would love a solution, every solution in that thread works if you do

wrapper() << "string"

but does not compile if you do

wrapper() << "string" << endl

EDIT: clarified about the old prototypes that I must not break.

Was it helpful?

Solution

The return type of << can be anything you want - just create your own type. The only real restriction is that the ostringstream code must work. Support for endl and other manipulators is trivial. Check this out:

#include <iostream>
#include <sstream>
#include <iomanip>

struct MyStream
{
    mutable std::ostringstream ss;

    MyStream() {}
    MyStream(std::ostringstream & oss) { ss << oss.str(); }
};

typedef std::ostream & (*manipulator_t) (std::ostream &);

const MyStream & operator << (const MyStream & s, manipulator_t m)
{
    s.ss << m;
    return s;
}

template <class T>
const MyStream & operator << (const MyStream & s, T v)
{
    s.ss << v;
    return s;
}

void MyPrint(const MyStream & s)
{
    std::cout << "logged: " << s.ss.str();
}

int main()
{
    MyPrint(MyStream() << "true && false == " << std::boolalpha << (true && false) << std::endl);

    std::ostringstream oss;
    oss << std::setw(22) << "Hello, World!" << std::endl;
    MyPrint(oss);
}

Online demo -> http://ideone.com/Gm7Cnc

OTHER TIPS

As you didn't get much replies, I posted the same question with some changes. Fortunately, I got the correct answer. Please look HERE.

Basically std::stringbuf of an std::ostringstream does not support reading as the flags passed are different due to which you are not getting any output.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top