I would like to use std::stringstream
to create formatted strings, but use the class inline so I don't have stringstream
local variables flying around. What I mean is this:
#include <iostream>
#include <ostream>
#include <string>
#include <sstream>
int main(int argc, char* argv[])
{
std::string test = ((std::ostringstream&)
(std::ostringstream("") << "This is a test: " << 50.1 << "abc")
).str();
std::cout << test << std::endl;
return 0;
}
This compiles fine in GCC, however the output is the following:
"0x401d0a50.1abc"
So it seems that stringstream
treats the first string as a pointer and outputs the address. Subsequent operator<<
's work fine.
How do I fix this? Thanks!
StringStream in C++ is similar to cin and cout streams and allows us to work with strings. Like other streams, we can perform read, write, and clear operations on a StringStream object. The standard methods used to perform these operations are defined in the StringStream class.
stringstreams are primarily there for convenience and type-safety, not speed. The stream will collect the input and then eventually call strtold for the conversion. Makes it hard to be any faster!
A stringstream is an iostream object that uses a std::string as a backing store. An ostringstream writes to a std::string . An istringstream reads from a std::string . You read & write from & to an istringstream or ostringstream using << and >> , just like any other iostream object.
str()- To get and set string object whose content is present in the stream. operator <<- Add a string to the stringstream object. operator >>- Read something from the stringstream object.
The reason is that the <<
operator is a member for void const*
, but a free function taking an std::ostream&
as the left hand argument for char const*
. Your std::ostringstream( "" )
is a temporary: you can call member functions (even non-const member functions) on it, but a temporary cannot be used to initialize the non-const reference of the global function.
EDIT:
Two points: first, as has been pointed out, g++ does do what you
want if you specify -std=c++11
. As T.C. points out, this is
specified in §27.7.3.9, which provides a template overload for
all <<
with an rvalue reference for the std::istream
parameter.
And second, the classic work around is
to start the expression std::ostringstream( "" ).flush() <<...
. flush
is a member function (and so can be called on
a temporary) which returns an std::ostream&
(so everything
else chains nicely); it also does nothing on
a std::ostringstream
.
Found it. The C++11 standard special-cases rvalue streams with an extra template operator<<
overload. §27.7.3.9 of the standard:
Rvalue stream insertion [ostream.rvalue]
template <class charT, class traits, class T> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&& os, const T& x);
Effects:
os << x
Returns:
os
It's obviously a better match than the member operator<<
that takes a const void *
and hence is selected by overload resolution in C++11 mode. In C++98 mode this overload doesn't exist (since there are no rvalue references) and the only viable overload is the member operator<<
(since, as James Kanze explains in his answer, the temporary can't bind to the non-const lvalue reference in the free operator<<
overload that takes a const char *
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With