Odd (?) Behavior of temporary std :: ostringstream

I was messing around with std::ostringstream , considering this question: sprintf in C ++? and noticed the packaging of stringbuilder() from Nawaz and thought it should work with std::ostringstream .

So my first attempt was as follows:

 std::cout << (std::ostringstream("select * from foo limit") << max_limit).str() << std::endl; 

Now this obviously does not compile (correctly), since the result of operator<< is std::ostream - which does not have str() member. Therefore, I thought that the actor should do the trick, and specifically, throw a const link on the link (also works with casting to a regular link), so the second attempt:

 std::cout << static_cast<std::ostringstream const&>(std::ostringstream("select * from foo limit") << max_limit).str() << std::endl; 

Now this compiles fine and works, however the output, well, is not what I expected.

10lect * from foo limit

Now - here is the question, do I cause some undefined behavior somewhere - and if so where? And how is this different from the approach that stringbuilder did (I suppose, in addition to the result of its operator, there is stringbuilder itself, and not std::ostream ).

EDIT: here is the ideone code .

EDIT: oops - forgot to specify, max_limit - int .

+4
source share
3 answers

You need to move the position of the stream to the end of the internal buffer used by ostringstream :

  std::ostringstream out("select * from foo limit ", std::ios_base::app); out << max_limit; std::cout << out.str () << std::endl; 

See the documentation in the ostringstream constructor.

+4
source

What is maxLimit ?

Some of the ostream operator<< overloads are free functions, such as:

 ostream& operator<<(ostream& os, T const&); 

If the stream is temporary (which in your case is), it cannot bind to this ref-to-non-const , and overload cannot be selected.

Thus, you may accidentally use invalid overload; perhaps a bit of an overload for char const* . It's hard to say without knowing what maxLimit .

This is a limitation when trying to do this serialization on one line, and you cannot get around it.

You are also trying to pass std::cout to std::cout , which is clearly not what you intended to do.

Update Vijay realized this.

 std::cout << static_cast<std::ostringstream const&>( std::ostringstream("select * from foo limit", std::ios_base::app) << max_limit ).str() << std::endl 

The foregoing is still definitely worth keeping in mind, however.

+2
source

You can also just use flush like:

 static_cast<std::ostringstream const&>(std::ostringstream().flush() << "select * from foo limit " << max_limit).str() << std::endl; 

But then the code is not the same. It uses the default constructor.

As a side element: is dynamic_cast more appropriate here?

Demo: http://www.ideone.com/06xNS

0
source

All Articles