Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Using stringstream after << as parameter

Is it possible to write a method that takes a stringstream and have it look something like this,

void method(string str)
void printStringStream( StringStream& ss)
{
    method(ss.str());
}

And can be called like this

stringstream var;
printStringStream( var << "Text" << intVar << "More text"<<floatvar);

I looked up the << operator and it looks like it returns a ostream& object but I'm probably reading this wrong or just not implementing it right.

Really all I want is a clean way to concatenate stuff together as a string and pass it to a function. The cleanest thing I could find was a stringstream object but that still leaves much to be desired.

Notes:

I can't use much of c++11 answers because I'm running on Visual Studio 2010 (against my will, but still)

I have access to Boost so go nuts with that.

I wouldn't be against a custom method as long as it cleans up this mess.

Edit:

With @Mooing Duck's answer mixed with @PiotrNycz syntax I achieved my goal of written code like this,

try{

    //code

}catch(exception e)
{   
    printStringStream( stringstream() << "An exception has occurred.\n"
                            <<"    Error: " << e.message 
                            <<"\n If this persists please contact "<< contactInfo
                            <<"\n Sorry for the inconvenience");
}

This is as clean and readable as I could have hoped for.

Hopefully this helps others clean up writing messages.

like image 308
Dan Avatar asked Sep 20 '12 19:09

Dan


3 Answers

Ah, took me a minute. Since operator<< is a free function overloaded for all ostream types, it doesn't return a std::stringstream, it returns a std::ostream like you say.

void printStringStream(std::ostream& ss)

Now clearly, general ostreams don't have a .str() member, but they do have a magic way to copy one entire stream to another:

std::cout << ss.rdbuf();

Here's a link to the full code showing that it compiles and runs fine http://ideone.com/DgL5V

EDIT

If you really need a string in the function, I can think of a few solutions:

First, do the streaming seperately:

stringstream var;
var << "Text" << intVar << "More text"<<floatvar;
printStringStream(var);

Second: copy the stream to a string (possible performance issue)

void printStringStream( ostream& t)
{
    std::stringstream ss;
    ss << t.rdbuf();
    method(ss.str());
}

Third: make the other function take a stream too

like image 134
Mooing Duck Avatar answered Oct 26 '22 11:10

Mooing Duck


Make your wrapper over std::stringstream. In this new class you can define whatever operator << you need:

class SSB {
public:
   operator std::stringstream& () { return ss; }

   template <class T>
   SSB& operator << (const T& v) { ss << v; return *this; }
   template <class T>
   SSB& operator << (const T* v) { ss << v; return *this; }
   SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
   // Be aware - I am not sure I cover all <<'s       
private:
   std::stringstream ss;
};

void print(std::stringstream& ss)
{
    std::cout << ss.str() << std::endl;
}

int main() {
  SSB ssb;
  print (ssb << "Hello" << " world in " << 2012 << std::endl);
  print (SSB() << "Hello" << " world in " << 2012 << std::endl);
}
like image 44
PiotrNycz Avatar answered Oct 26 '22 09:10

PiotrNycz


For ease of writing objects that can be inserted into a stream, all these classes overload operator<< on ostream&. (Operator overloading can be used by subclasses, if no closer match exists.) These operator<< overloads all return ostream&.

What you can do is make the function take an ostream& and dynamic_cast<> it to stringstream&. If the wrong type is passed in, bad_cast is thrown.

void printStringStream(ostream& os) {
    stringstream &ss = dynamic_cast<stringstream&>(os);
    cout << ss.str();
}

Note: static_cast<> can be used, it will be faster, but not so bug proof in the case you passed something that is not a stringstream.

like image 3
quantum Avatar answered Oct 26 '22 11:10

quantum