Stream buffers and rdbuf() question

K

kelvSYC

Suppose I have something like this:

class foo {
std::istream in;
public:
foo(std::istream& in_) : in(in_.rdbuf());
void doStuffWith(std::eek:stream& out);

void bar();
};

where doStuffWith reads stuff from in and writes stuff to out.

Now, suppose bar() was like this:

void foo::bar() {
std::eek:stringstream out;
doStuffWith(out);
in.rdbuf(out.rdbuf());

// read stuff from in
}

and a foo object was instantiated with an std::ifstream. At the end
of bar(), we would expect that you would effectively read the
characters that were put into out from doStuffWith(). Yet, I keep
reading from the (beginning of the) original filebuf instead. Why is
this going on, and how can I fix it so it does what I expect it to do?
 
D

Dietmar Kuehl

kelvSYC said:
std::eek:stringstream out;
doStuffWith(out);
in.rdbuf(out.rdbuf());

At best, the stream buffer created for 'out' is not constructed
to perform input operations. The standard definitely mentions that
depending on the "mode" flags passed the stream is for reading or
writing. It does not, however, spell out what happens when the
stream is used in violation to these flags.
and a foo object was instantiated with an std::ifstream. At the end
of bar(), we would expect that you would effectively read the
characters that were put into out from doStuffWith(). Yet, I keep
reading from the (beginning of the) original filebuf instead.

Can you post complete code which exhibits this problem? It sounds
extremely unlikely and I don't see any reason why this should
happing.
 
K

kelvSYC

Dietmar Kuehl said:
At best, the stream buffer created for 'out' is not constructed
to perform input operations. The standard definitely mentions that
depending on the "mode" flags passed the stream is for reading or
writing. It does not, however, spell out what happens when the
stream is used in violation to these flags.

True. As I found out with further experimentation, you'd need to copy
the buffer with something like:

std::stringbuf buf(out.str());
in.rdbuf(&buf);

after doStuffWith(out), or instead have

std::stringbuf outbuf;
std::eek:stream out(&outbuf);
doStuffWith(out);
in.rdbuf(out.rdbuf());

.... guess I was unaware of the completely obvious observation that
streambufs that are created with ostreams are built with only out-mode
enabled (and similarly for istreams).

It still smells of real redundancy with istreams, ostreams, and
iostreams (not to mention the counterintuitive fact that an iostream is
descended from istream and ostream but an fstream is not a descendant
of ifstream and ofstream), as you're now dealing at the streambuf
level. (This is one of those times I wish C++ had say Java's streaming
classes...)

The only plausible explanation that I can come up with this behavior is
that setting the streambuf resets the streambuf's buffer pointers, and
that some streambufs keep separate input and output buffers. That
still doesn't explain why in.rdbuf(out.rdbuf()) had no effect, even if
the streambuf replacement was successful (and a filebuf was replaced by
a stringbuf).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top