I was messing around with std::ostringstream
whilst looking at this question: sprintf in c++?, and noticed the stringbuilder()
wrapper by Nawaz and thought, well that ought to work with std::ostringstream
.
So my first attempt was the following:
std::cout << (std::ostringstream("select * from foo limit") << max_limit).str() << std::endl;
Now this obviously fails to compile (correctly) as the result of the operator<<
is a std::ostream
- which doesn't have the member str()
. So I thought a cast should do the trick, and specifically a cast to a const
reference (works with a cast to a normal reference too), so 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 runs, however the output is, well, not what I was expecting.
开发者_JS百科10lect * from foo limit
Now - here's the question, am I invoking some undefined behaviour somewhere - and if so where? And how is this different to the approach that Nawaz has taken (I guess aside from the result of his operator is the stringbuilder
itself rather than std::ostream
).
EDIT: here is the ideone code.
EDIT: oops - forgot to specify, max_limit
is int
.
You need to move the stream's position 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 on ostringstream
constructor.
What's maxLimit
?
Some of the ostream
operator<<
overloads are free functions, like:
ostream& operator<<(ostream& os, T const&);
If the stream is a temporary (which in your case it is), it cannot bind to that ref-to-non-const
, and the overload cannot be chosen.
So you may be using a non-preferred overload by accident; possibly something like the overload for char const*
. Hard to tell without knowing what maxLimit
is.
This is a limitation when trying to do this serialisation on a single line, and you can't get around it.
You're also attempting to stream std::cout
to std::cout
, which is obviously not what you intended to do.
Update Vijay figured it out.
std::cout << static_cast<std::ostringstream const&>(
std::ostringstream("select * from foo limit", std::ios_base::app) << max_limit
).str() << std::endl
The above is still definitely worth bearing in mind, though.
You could also simply use flush
as:
static_cast<std::ostringstream const&>(std::ostringstream().flush() << "select * from foo limit " << max_limit).str() << std::endl;
But then the code is not same. Its using default constructor.
As a sidenote : isn't dynamic_cast
more appropriate here?
Demo : http://www.ideone.com/06xNS
精彩评论