Odd(?) behaviour of a temporary std::ostringstream - c++

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

Related

C++: Is it possible to get a std::string out of an object that overloads the << operator?

I have an object that can be printed to the console with std::cout << obj, but I can't get a std::string out of it, because it doesn't seem to implement something like a .string() method. I thought I might be able to use that overloaded operator to just get string representations of everything instead of having to implement a function to do it myself every time I need it, though having found nothing on the subject makes me think this isn't possible.
Use a std::ostringstream. It is a C++ stream implementation which writes to a string.
You can use a std::ostringstream.
std::ostringstream os;
os << obj;
std::string result = os.str();
There are different ways of doing it, you can manually implement it in terms of std::ostringstream, or you can use a prepacked version of it in boost::lexical_cast. For more complex operations, you can implement a in-place string builder like the one I provided as an answer here (this solves a more complex problem of building generic strings, but if you want to check it is a simple generic solution).
It seems that the linked question has been removed from StackOverflow, so I will provide the basic skeleton. The first think is to consider what we want to use with the in-place string builder, which basically is avoiding the need to use create unnecessary objects:
void f( std::string const & x );
f( make_string() << "Hello " << name << ", your are " << age << " years old." );
For that to work, make_string() must provide an object that is able to take advantage of the already existing operator<< for the different types. And the whole expression must be convertible to std::string. The basic implementation is rather simple:
class make_string {
std::ostringstream buffer;
public:
template <typename T>
make_string& operator<<( T const & obj ) {
buffer << obj;
return *this;
}
operator std::string() const {
return buffer.str();
}
};
This takes care of most of the implementation with the very least amount of code. It has some shortcomings, for example it does not take manipulators (make_string() << std::hex << 30), for that you have to provide extra overloads that take the manipulators (function pointers). There are other small issues with this implementation, most of which can be overcome by adding extra overloads, but the basic implementation above is enough for most regular cases.

Printing Stringstream Outputs Pointer

Rather than outputting the expected string of "Bar", the following code outputs what looks to be a pointer.
#include <sstream>
#include <iostream>
int main()
{
std::stringstream Foo("Bar");
std::cout << Foo << std::endl; // Outputs "0x22fe80."
return 0;
}
This can be worked around by using Foo.str(), but it's caused some issues for me in the past. What causes this strange behavior? Where is it documented?
This can be worked around by using Foo.str(), but it's caused some issues for me in the past. What causes this strange behavior? Where is it documented?
It's not strange at all.
A stream is a stream, not a string.
You can obtain the [string] buffer with the member function .str(). That's not a workaround: it's the API. It should be documented in your C++ standard library reference, and if it's not then your reference is incomplete/wrong.
(What is slightly strange is that you get a memory address rather than a compilation error; that is due to the use of the safe bool idiom in the pre-C++0x standard library, as covered in another answer.)
A std::stringstream is not supposed to be inserted in a stream. That's why you have the str() method.
The behavior you're observing is due to the fact that std::stringstream has a conversion to void*, which is what is used to test the stream:
if(Foo) { // this uses the conversion to void*
}
In C++11, this conversion is replaced by an explicit conversion to bool, which causes this code not to compile:
std::cout << Foo << std::endl;
(1)use std::cout << Foo << std::endl; you should make sure stringstream has already overload "<<".
(2)if there is not overload "<<" , use std::cout << Foo << std::endl; may output the Foo's address.

Support for const_string in std::ostream operator <<

I'm currently using the very clever package boost::const_string until http://libcxx.llvm.org/ is available pre-packaged on Ubuntu or GCC make its __versa_string (in header ext/vstring.h) its default string implementation. libcxx's std::string aswell as __versa_string uses _small-string optimization (SSO) by default. Default support for outputting to an std::ostream is lacking however. The code
#include <iostream>
#include <boost/const_string.hpp>
const_string<char> x;
std::cout << x << endl;
does not work unless we force x into a c-string via c_str() which becomes
std::cout << x.c_str() << endl;
which compiles and works as expected. I added the following line to const_string.hpp
template <typename T>
inline std::ostream & operator << (std::ostream & os, const boost::const_string<T> & a)
{
return os.write(a.data(), a.size());
}
This should improve performance over x.c_str() because size() is already known and does not need to be calculated by searching for NULL as in c_str(). I works for me but I am uncertain whether it works all cases. Have I missed something?
Have I missed something?
Yes, just include const_string/io.hpp. All it does however is:
return o << std::basic_string<char_type, traits_type>(s.data(), s.size());
It seems that this could have implications based on the locale and/or facets applied to the stream for strings vs just writing the straight data as you're doing.
It would be less performant, but what about creating a std::string from the const_string and using << to insert that into the stream?
No (you have not missed anything, afaik). If your aim is not to copy over content, str.data() is the way to go.

In C++, using operator<< to construct input for a function

I would like to be able write code that looks like this:
int n;
std::string s = "some string";
SomeFunction("hello world" << n << " " << s << std::endl);
Where SomeFunction() is a method of some other class. The point is that I would like to be able to construct input for certain method using operator<<, just the way one'd do when writing to standard output in C++. How can I do that?
Thanks.
Your first parameter would have to be a home-made type that overloads operator<< and builds some kind of parameter list.
Your class would probably contain an ostream and would forward the operator<< to it.
If the function takes a string rather than your mysterious string-building object, you would then need to convert your object back to a string.
You could do it aleady with ostringstream like this:
int n;
std::string s;
std::ostringstream oss;
SomeFunction( ( oss << "hello world " << n << " " << s << '\n' ).str() );
Thanks, but this solution is way too obvious. I am looking for the code to remain the same as in the sample. – Alexander Sandler 54 secs ago
A surprising bias against obvious solutions?
Your syntax just cannot be achieved (in general[1]) without the macro that you describe in the first comment. Period.
[1] In specific cases you might be able to force the issue by overloading to ostream& operator<<(std::string, myspecifictype). In practice this will give you nothing but headaches because just about every use of the << operator will subsequently result in ambiguous overload resolutions

Transparently manipulating strings inserted into an ostream

I'd like to provide an std::ostream that may or may not, from the user's point of view, encrypt its contents.
Imagine some random function that uses an std::ostream&:
void write_stuff( std::ostream& stream ) {
os << "stuff";
}
Whether stuff is output in cleartext or is encrypted is dependent on how the stream argument was initialized.
I'm thinking about inheriting from std::basic_streambuf, but I'm not sure it's the best way to go. I think the ideal scenario is some sort of filter object which is run before the contents are actually output. That way it'd be easy to chain operations, e.g. encrypting and then hex-encoding, which is a benefit that making my own basic_streambuf does not seem to give (not easily at least).
Any advices?
Thanks.
UPDATE: I followed the strategy laid out by the accepted answer. I found this article on writing a custom streambuf which performs XOR obfuscation to be extremely helpful as a starting point.
A streambuf can be implemented in terms of another arbitrary streambuf that's either passed in as an argument to the constructor or set with a special member function. And that allows you to stack streambuf implementations like you were thinking of.
You could even make a manipulator that uses the ostream's rdbuf function to get the current streambuf, call a function on your streambuf that sets the 'stacked' streambuf, and then calls rdbuf again to replace the ostream's streambuf with your own.
aes_ctr_streambuf encrypter(key);
zlib_streambuf compressor;
::std::cout << stack_streambuf(encrypter) << stack_streambuf(compressor);
It is hard to describe in short what you have to do in order to create an I/O stream for the new source or sink. Luckily, Jonathan Turkanis and CodeRage, LLC have created very nice building blocks with exceptional documentation that can help you save hundreds of hours of research and development of new streams. The library is called Boost.Iostreams.
The second example in documentation exactly shows how to solve your problem.
Also, note that they already have an output stream with zip compression. So maybe you don't even need to write a single line of code.
Good luck!
I'm not sure that what I'm about to suggest is exactly what you need (and its too complicated to be a comment), but have you ever heard of the stream manipulators ?
#include <iostream>
#include <iomanip>
int main(int, char**)
{
int a = 10;
std::cout << "a: " << a << std::endl; //outputs: "a: 10"
std::cout << "a: " << std::hex << a << std::endl; //outputs: "a: a"
std::cout << "a: " << std::dec << a << std::endl; //outputs: "a: 10"
return EXIT_SUCCESS;
}
You may indeed use a similar pattern (this matches what you actually call a "filter" object) to somehow change the state of your custom stream object.