Stringstream: mixing str() and operator<<

I'm trying to convert data using stringstreams, but the behaviour is not what I'd expect. To illustrate, I created the following test application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <sstream>

using namespace std;

int main(int argc, char argv[])
{
	stringstream a("Hello, ");
	stringstream b("Hello, ", ios::app);
	stringstream c("Hello, ", ios::ate);
	stringstream d("Hello, ", ios::out || ios::app);
	stringstream e("Hello, ", ios::out || ios::ate);
	ostringstream f("Hello, ");

	a << "World!";
	b << "World!";
	c << "World!";
	d << "World!";
	e << "World!";
	f << "World!";

	cout << '"' << a.str() << '"' << endl; // "World! "
	cout << '"' << b.str() << '"' << endl; // ""
	cout << '"' << c.str() << '"' << endl; // ""
	cout << '"' << d.str() << '"' << endl; // "Hello, "
	cout << '"' << e.str() << '"' << endl; // "Hello, "
	cout << '"' << f.str() << '"' << endl; // "World! "

	cin.get();

	return 0;
}


Intuitively, I'd expect most of the couts to produce "Hello, World", but the result (in the comment after the cout) is very different.

Can somebody explain the result to me and/or show me a way to print "Hello, World!" by mixing str() and operator<<()?

Thanks,
Jonas
Does your code even compile? Because you have the || for lines 11 and 12 and g++ barks about that. You should switch it to | unless there's something I don't understand about that.

My output after I fix that compilation problem is:

"World! "
"Hello, "
"Hello, "
"Hello, World!"
"Hello, World!"
"World! "


Which I believe makes sense based on your settings.
O oh... you're absolutely right, of course it should be | instead of ||. Microsoft Visual C++ doesn't complain about it :-(

The output with MSVC++ after changing the || to | is as follows:
"World! "
""
""
"World! "
"World! "
"World! "


Somehow, g++ seems to make much more sense than vc++...
Last edited on
hmm, I've never used MSVC++ so I can't really help with that. I'm sorry. All I know is that based on the code you have (with the | fix), it prints out what I have for my normal X-win32, emacs, and g++ combo.
ios::out || ios::app is a legal if somewhat suspicious statement (although not the programmer really wanted). It returns true or false which can be silently cast by the compiler to the required type
(probably int) - that's why VC++ probably didn't complain but G++ probably thought it
suspicious.

With regards to the difference in the two outputs where VC++ gave empty strings: - I'm surprised at G++ output, because I see it this way:

1
2
	stringstream b("Hello, ", ios::app); //you have only specified appending and neither  input or output
	stringstream c("Hello, ", ios::ate); //again no direction in or out specified. 


Certainly with VC++ - the Append flag on its own doesn't work. You need ios::out|ios::app
Thank you two for your replies!

GuestGulkan, your write that I need ios::out | ios::app. However this does not produce the desired result (see above).

Anyway, you can use this incongruency to produce interesting effects:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <sstream>

using namespace std;

int main()
{
	stringstream messageStream("like", ios::out | ios::app);
	messageStream << "hate";

	cout << "I " << messageStream.str().substr(0, 4) << " my compiler!" << endl;
    
	cin.get();

	return 0;
}


This (absolutely standard-conforming) program prints "I like my compiler" if compiled with gcc, and something rather different when compiled with VC++.

Should we report this as a bug in either compiler or is it just undefined in the standard? Does anybody know which result the standard would require?
Topic archived. No new replies allowed.