From: Niels Dekker - no return address on
Does the Standard Library support creating an std::string by means of
streaming, without having to declare a *named* ostringstream object? I tried
the following:

#include <sstream>
#include <string>
int i = 42;

std::string s = (std::ostringstream() << "i = " << i).str();

Of course it didn't compile, because a temporary (std::ostringstream()) cannot
be passed as non-const reference to a function (operator<<). Okay, second
try, wrapping the ostringstream as follows:

template <typename T> class Wrapper {
T m_data;
public:
T & get() {
return m_data;
}
};

std::string s = (Wrapper<std::ostringstream>().get() << "i = " << i).str();

Unfortunately it still didn't compile, because operator<< returns an
std::basic_ostream, instead of an std::ostringstream, and therefore it doesn't
have an str() member function. Now I wonder, is it safe to cast the stream,
returned by operator<< to an ostringstream reference? As follows:

std::string s =
static_cast<std::ostringstream&>(Wrapper<std::ostringstream>().get()
<< "i = " << i).str();

At least, it *seems* to work... But is it the proper way to do it?


Kind regards,
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin York on
On Apr 23, 12:14 pm, "Niels Dekker - no return address"
<nore...(a)this.is.invalid> wrote:
> Does the Standard Library support creating an std::string by means of
> streaming, without having to declare a *named* ostringstream object? I tried
> the following:

<DELETED>

>
> At least, it *seems* to work... But is it the proper way to do it?


Is your problem that you have other objects of non string types that
you want to append onto a string. In this case you could use
boost::lexical_cast()


std::string s = std::string("i =
").append( boost::lecical_cast<std::string>(i) );

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Peter Jones on
"Niels Dekker - no return address" <noreply(a)this.is.invalid> writes:
> Does the Standard Library support creating an std::string by means of
> streaming, without having to declare a *named* ostringstream object?

What's wrong with:

,----
| #include <iostream>
| #include <sstream>
| #include <string>
|
| int main (int argc, char *argv[])
| {
| std::ostringstream os;
| int i = 42;
|
| os << "i=" << i;
| std::string s = os.str();
|
| std::cout << s << std::endl;
| }
`----

Are you just trying to make your code as terse as possible? Why would
you want to create a string from an ostringstream without having to
use a named ostringstream?

--
Peter Jones [pjones at domain below]
pmade inc. - http://pmade.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carl Barron on
In article <480ef5ff$0$14345$e4fe514c(a)news.xs4all.nl>, Niels Dekker -
no return address <noreply(a)this.is.invalid> wrote:

> Does the Standard Library support creating an std::string by means of
> streaming, without having to declare a *named* ostringstream object? I tried
> the following:
>
> #include <sstream>
> #include <string>
void foo()
{
> int i = 42;
>
> std::string s = (std::ostringstream() << "i = " << i).str();
>
}


No but, most general and easiest solution is to put the ostringstream
in a block.

void foo()
{
int i= 42;
std::string s;

{
std::ostringstream oss;
oss << "i = " << i ;
s = oss.str();
}
}

this has the same effect as what your errant code is supposed to do.
and does not flood the code with temp variables that live longer than
needed. that is the ostringstream is destroyed on exit from the short
block.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Vidar Hasfjord on
On Apr 23, 8:14 pm, "Niels Dekker - no return address"
<nore...(a)this.is.invalid> wrote:
> std::string s = (std::ostringstream() << "i = " << i).str();
> Of course it didn't compile, because a temporary (std::ostringstream())
cannot
> be passed as non-const reference to a function (operator<<).

Well, that is not the case on the implementations I use (VC7.1/VC9.0).
The << operator is implemented as a member of ostream; which does bind
to temporaries; so this works fine:

ostringstream () << "i = " << i; // compiles

I don't know if the standard mandates this or not though.

> Unfortunately it still didn't compile, because operator<< returns an
> std::basic_ostream, instead of an std::ostringstream, and therefore it
doesn't
> have an str() member function.

Yes, the reason it doesn't work is type erasure. The first application
of << returns ostream&, and ostringstream::str can not be applied to
an ostream.

> Now I wonder, is it safe to cast the stream, returned by operator<< to an
> ostringstream reference?

Yes, you can recover the type in this way, but pedantically you should
use a dynamic_cast to do so.

dynamic_cast <ostringstream&> (ostringstream () << ...).str ();

This is ugly and verbose though. An alternative wrapper solution that
I use is based on forwarding the << operator call:

struct S { // string builder
std::ostringstream s;

template <typename T>
inline S& operator << (const T& v) {
using ::operator <<; // Note: Ugly disambiguation.
s << v;
return *this;
}
inline operator std::string () const
{return s.str ();}
};

Usage:

string s = S () << "i = " << i;

This works for me in practice. But you may stumble into problems
caused by less-than-perfect forwarding (e.g. ambiguities). I haven't
studied the best solution to this yet.

Regards,
Vidar Hasfjord

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]