Re: Curious question about the STL ostream
On Sep 9, 2:14 pm, Rolf Magnus <ramag...@t-online.de> wrote:
Alf P. Steinbach wrote:
I think it's just a design level error resulting from some misguided
principle that having them as members clutters the class interface.
A result is that if you do
(std::ostringstream() << "bah").str()
you'll probably invoke the member <<(void*) function (because a
temporary can't be bound to the reference argument in the free
functions), which produces the address of the "bah" string instead of
the characters.
The above doesn't work anyway, since operator<< returns a reference to
ostream, which doesn't have a member function str().
So you need a cast. Most of the time, you would be doing
something more along the lines of:
//! \pre message must in fact be an std::ostringstream
void f( std::ostream& message ) ;
// ..
f( std::ostringstream() << "bah" ) ;
with a dynamic_cast in f.
However,
std::ofstream("test.txt") << "bah";
writes the result you're describing into a file. It writes the
address instead of the string itself.
Note that this changed with the standard iostream. In the
classical iostream, the operator<< for a char const* was a
member.
There was a trick around that:
std::ofstream("test.txt").flush() << "bah";
flush() can be called on a temporary, and it returns a
reference, so this will now write the string to the file. This
is a nice quiz question for C++ programmers ;-)
I agree that the behavior is quite unexpected. However, you'll
have the same problem with your own overloaded operators, and
it seems to me that temporary stream objects are hardly useful
anyway.
Unless you're abusing user defined conversions, you should get
an error with your own types. And historically, the work-around
for this error was:
ofstream( "text.txt" ) << "" << myType ;
The standard streams broke that idiom.
Like Alf, I think that there is a design level error. The
classical iostream couldn't make everything a member, since the
user defined conversions couldn't be members. (There were no
member templates at the time.) But logically, they all should
be members; you don't want the stream parameter to be the result
of an implicit conversion. So the classical iostream
compromized: the pre-defined operators (those in <iostream.h>)
where members, and user defined operator could be non-members.
The standard should have either left it this way, or made the
operator<< a template member function, without a generic
implementation, and with explicit specializations for all
types. (The user can provide an explicit specialization for
such a template member.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34