Protazy wrote:
Quote:
From what I understood, it is not a member operator used here. It's a friend
function. Right?
Sorry, I overlooked the "member". Yes it's a friend (or a non-friend
free function, depending on the implementation).
Quote:
What worries me is the bahaviour of:
f(std::ostringstream() << test << "some text");
In the first "<<" the member operator is used, but for second "<<" friend
function is invoked. Is the variable produced by first "<<" "less temporary"
then the variable produced by std::ostringstream()?
Yes, it's less temporary. :)
The return value of operator << in this context is ostream &, which is a
non-const reference. In particular, it's an lvalue expression, where
std::ostringstream() is a temporary, ie. an rvalue expression. And
though what's returned by the first << operator expression is still the
same temporary, the expression is now an lvalue expression. lvalues bind
to non-const references, rvalues don't.
In this case, it seems weird and arbirtary, but usually it's what you
want since it's usually a programming error to pass an object by
reference (non-const, to modify it), if it's going to be destroyed after
the end of the expression. The essence of what happened in your example
is that it got explicitly casted to an lvalue.
Quote:
Why? Is it dangerous? I only need it to extract string from it. I want to do
something like:
f(std::stringstrem() << "The value is " << 2 << " and some object is " <<
someobject);
Operator << on ostringstreams returns ostring&, so you can't call str on
it, that's why you made your f take an ostream and cast it down. While
legal, I don't really like it: The function is lying about what's it's
really accepting in it's signature, and somone who doesn't realise the
hack might put another kind of ostream in it at some point; which will
probably crash the program.
A better way is wrapping it into your own helper stream class:
struct make_string
{
template< typename T >
make_string & operator <<(T const& t)
{
m_s << t;
return *this;
}
operator std::string ()
{
return m_s.str();
}
private:
std::ostringstream m_s;
};
And then use it like
void foo(std::string const& str)
{
std::cout << str;
}
int main()
{
foo(make_string() << "Hello " << 42);
}
There is a more sophisticated class like this in boost, supporting
expressions like format("this: %1% and that: %2%") % these % those
(maybe the syntax is slightly different).
Quote:
The variable should last long enough to be passed to the function. Or am I
missing something here?
Yes, it lasts long enough.
Jens