简体   繁体   中英

C++ stringstream inline

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!

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 TC 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 * ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM