问题
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!
回答1:
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
.
回答2:
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 *
).
来源:https://stackoverflow.com/questions/24494761/c-stringstream-inline