问题
I want to read directly into a string with code like this:
std::string myString(( std::ostringstream() << myInt << " "
<< myFloat << " "
<< std::boolalpha << myBool ).str());
But VS2012 is giving me a complaint that basic_ostream
doesn't have an str()
method.
Is there a way to do this with an anonymous stringstream?
回答1:
The operator<<
for streams returns std::ostream &
which doesn't have str()
member function. You need to use cast.
static_cast<std::ostringstream&>(std::ostringstream() << etc).str()
Differences between C++03 and C++11 when using temporary stream!
C++03
But be aware (in C++03) that std::ostringstream()
creates a temporary object, which means the non-member overloads of operator<<
cannot be invoked for the first <<
because all of them accepts the first argument as std::ostream&
which cannot bind to the temporary object. The temporary object will be able to invoke only member functions.
That means, the following would give you address instead of string:
static_cast<std::ostringstream&>(std::ostringstream() << "XYZ").str()
Because the overload which takes char const*
as argument is a non-member function, which cannnot be invoked, so the above code end up calling the member function which takes void const*
as argument and thus "XYZ"
is implicitly converted into void const*
, which prints address of string literal.
Once the temporary invokes the member function, the remaining chained <<
may invoke non-member overloads, because the member function return std::ostream&
which now can bind to the first argument to the non-member overloads of operator<<
. So this following code would print an address (instead of "XYZ"
) followed by string "ABC"
:
static_cast<std::ostringstream&>(std::ostringstream() << "XYZ" << "ABC").str()
Online demo:
- GCC output without
-std=c++11
- Clang output without
-std=c++11
C++11
In C++11, this issue has been fixed by adding a non-member function (27.7.3.9) which takes the first argument as rvalue reference which then forwards the call to the appropriate function, either member or non-member. So it prints XYZ
followed by ABC
:
- GCC output with
-std=c++11
- Clang output with
-std=c++11
回答2:
basic_osstream::operator<<
returns a basic_ostream
, not a ostringstream
. The compiler is not lying to you.
I would rather create a StringBuilder type device.
class StringBuilder
{
public:
template <typename T> inline StringBuilder& operator<<(const T& t)
{
mStream << t;
return * this;
}
inline std::string get() const
{
return mStream.str();
}
inline operator std::string () const
{
return get();
}
private:
std::stringstream mStream;
};
Now you can:
std::string myString (StringBuilder() << myInt << " " << myFloat /*...*/);
There are also similar devices in Boost -- you would do well to use those instead if it is available to you.
回答3:
I had this problem too, and John answer seems fine, thanks a lot! - I tried to build a string by using the operator '<<' onto a 'stringstream', and it did compiled & worked fine with 'clang' on macOS but not with 'gcc' on ubuntu, (compiling with -std=c++11 on modern updated compilers), it looks like in the Mac machine the operator is returning a stringstream instead of a basic_ostream......
Here is a minimal program which does not compiles with g++ but compiles with clang (experimental concepts), as tested in the Compiler Explorer (godbolt.org):
#include <iostream>
#include <sstream>
#include <string>
int main()
{
using namespace std;
cout << ((stringstream() << "hola").str()) << endl ;
}
来源:https://stackoverflow.com/questions/19665458/use-an-anonymous-stringstream-to-construct-a-string