Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 600
ElOmmy Avatar asked Jun 30 '14 16:06

ElOmmy


People also ask

Can we use Stringstream in C?

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.

Is Stringstream fast?

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!

What is the difference between Istringstream and Stringstream?

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.

What does Stringstream str () do?

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.


2 Answers

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.

like image 61
James Kanze Avatar answered Oct 17 '22 00:10

James Kanze


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

like image 41
T.C. Avatar answered Oct 16 '22 23:10

T.C.