Why I can't just create an "empty" stream for my output like this
std::ostream out;
?
This rows is apparently illegal with both clang 3.4
and gcc 4.8.1
under linux with libstdc++
, I really don't get why, I mean why I can't just create a stream out of nowhere and use it like I want to ? notice that std::ofstream out;
is 100% ok instead. I just don't get the logic behind this.
This is even stranger if you consider that after the creation I can just use this buffer and share a common buffer with other buffers with copyfmt
so there is no real need for my std::ostream
to be initialized to something right from the creation of the object to be useful.
Please don't deviate from this, I don't need stringstreams
, I need ios
streams because of what I have to do and because of the methods and the properties that they are offering.
I'll admit that I don't understand it either. I can't find any
default constructor at all for std::istream
, and I would think
you would want one if you want to create a bidirectional stream,
because of the strange way std::ios_base
works: the
constructor does not initialize anything, but the derived
class must call std::ios_base::init
explicitly in its
constructor. When multiple inheritance is involved (i.e.
bidirectional IO, where the class derives from both
std::istream
and std::ostream
), I would expect only the most
derived class to call std::ios_base::init
. (In
std::iostream
, std::ios_base::init
will be called twice.)
In fact, before looking it up in the standard, I was about to
answer that the default constructor was protected, because it
didn't call std::ios_base::init
, and using it directly, rather
than in a derived class, would result in an uninitialized
stream.
Anyhow, your immediate problem has a simple solution:
std::ostream out( NULL );
Also: the function you need to set up its sink later is the
non-const version of rdbuf()
, not copyfmt()
. rdbuf()
is
used to read and to set the pointer to the streambuf
,
copyfmt()
copies the formatting flags, but does not touch
the pointer to streambuf
.
So you can do things like:
std::ostream out( NULL );
// ...
std::filebuf fileBuffer;
if ( filenameGiven ) {
fileBuffer.open( filename.c_str(), std::ios_base::out );
}
if ( fileIsOpen() ) {
out.rdbuf( &fileBuffer );
} else {
out.rdbuf( std::cout.rdbuf() );
}
(I do this a lot. In fact, I thought that it was the usual
idiom when you didn't know up front whether to output to a file
or to std::cout
.)
EDIT:
And yet another correction: the non-const version of rdbuf
calls clear()
,
so you don't have to. (I knew I'd done this without calling clear()
, but
when I saw that init
set badbit
...)
Anyhow: the summary is: it's usually preferrable to pass a pointer to a valid
streambuf to the constructor of std::ostream
, but if you can't, it's
perfectly valid to pass a null pointer, and set a valid pointer later using
rdbuf()
. And the answers which say otherwise are simply wrong.