简体   繁体   中英

Can a temporary stringstream object be used?

This works:

stringstream temp;
temp << i;
result_stream << transform(temp.str());

( transform is a function that takes a string and returns a string ; i is an int ). However, my attempt to let C++11 create a temporary object without a name didn't work:

result_stream << transform((stringstream() << i).str());

I thought it would work, since the second << should just return the first argument and I'd be able to use str() on that. But I get this error:

error: 'class std::basic_ostream<char>' has no member named 'str'

I'm using g++ 4.8.1 (MinGW-W64).

Is there a way to accomplish this (ie write code like this using an unnamed temporary)? (The above code is a bit simplified, and the actual code involves using << on arguments other than int .)

This doesn't work because the second << is std::ostream &operator<<(std::ostream &, int); and so the return type is ostream& which has no member str() .

You would have to write:

result_stream << transform( static_cast<stringstream &>(stringstream() << i).str() );

Update (2019): According to LWG 1203 the standard may be changed in future (and one major implementation already has) so that this code no longer works, and a simpler code works instead. See this question for detail.

In the interim period, apparently the following works on both old and new:

result_stream << transform( static_cast<stringstream &>(stringstream().flush() << i).str() );
//                                                                    ^^^^^^^^

This should not be a performance penalty since flushing an empty stream has no effect...

The result of the << operator on the temporary stringstream is an ostream . There is no str() method on an ostream .

Use to_string instead:

using std::to_string;

result_stream << transform(to_string(i));

You can define a helper to_string to handle objects not covered by std::to_string .

template <typename T>
std::string to_string (const T &t) {
   std::ostringstream oss;
   oss << t;
   return oss.str();
}

For example, if you had a class Foo that understood redirection to an ostream , and f was an instance of Foo , then you could do:

result_stream << transform(to_string(f));

Try it online!

If you actually want to use a lot of redirection to build up a string before transforming, you could create a helper object for that as well.

struct to_string_stream {
    std::ostringstream oss;
    template <typename T>
    auto & operator << (const T &t) { oss << t; return *this; }
    operator std::string () const { return oss.str(); }
    void clear () { oss.string(std::string()); }
};

Then, you could do something like:

to_string_stream tss;
result_stream << transform(tss << i << ':' << f);

Try it online!

operator<<() returns a reference to the base class std::ostream contained within the std::stringstream . The base class doesn't contain the str() method. You can cast it back down to a std::stringstream& :

result_stream << transform(static_cast<std::stringstream&>(std::stringstream() << i).str()); 

Tried and failed to do this for C++11 (in 2009):

http://cplusplus.github.io/LWG/lwg-active.html#1203

libc++ went outlaw and implemented it anyway.

It is up for reconsideration, but can not possibly be standardized prior to 2017 (standardization is a glacial process).

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