4

So I got stuck on a simple print-function today and I really don't know how to fix this problem. Basically I want to pass my Strings to a function in a std::cout-style like this:

foo(std::ostringstream() << "Hello" << " World!"); 

And from what I've read it should be possible by a function along the lines of

void foo(std::ostringstream& in) 

but when implementing I get a somewhat strange behavior:

#include <iostream> #include <sstream> void foo(std::ostringstream& in) { std::cout << in.str(); } int main() { std::ostringstream working; working << "Hello" << " World!"; foo(working); // OK std::ostringstream notWorking; notWorking << "Hello"; foo(notWorking<<" World!"); // Not OK?! return 0; } 

While the first call of foo seems fine and works like expected, the second one refuses to compile even though they should (from my perspective) be technically the same thing.

Error:

error C2664: 'void foo(std::ostringstream &)': cannot convert parameter 1 from 'std::basic_ostream<char,std::char_traits<char>>' to 'std::ostringstream &' 

I'm using MS Visual Studio 2013 Express on Win7 x64

3 Answers 3

4

The overloads of shifting operators for IO operations take the base streams by reference. That is:

std::ostream& operator<<( std::ostream& os , foo myfo ) { os << myfoo; return os; } 

So use std::ostream instead of std::ostringstream as function parameter:

void f( std::ostream& stream ); 
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that seems to be working. How do I get back from an std::ostream to std::string though? Shifting it into std::cout doesn't seem to work for example.
@CyDek If foo really needs an ostringstream you should use your working method instead of modifying the function to take an ostream. If you really want to follow your other method, then you could cast the ostream back to ostringstream (static_cast<std::ostringstream&>(in).str()) but then it'd be undefined behavior if someone calls foo with some other kind of ostream
@Praetorian Thanks, works like a charm. Since I'm really just experimenting for learning purposes I am actually quite fine with that :)
2

It's simply because the second expression

notWorking<<" World!" 

returns a std::ostream& not a std::ostringsream&.

Comments

0

The reason for your error is that you’re trying to implicitly downcast an ostream into an ostringstream because the result of the << operator is always ostream& regardless of the concrete string type. Changing foo() to take an ostream& ought to solve this, unless you need to rely specifically on ostringstream features in the implementation of foo, in which case you can dynamic_cast.

Also, by constructing a temporary ostringstream in your foo(std::ostringstream() << "Hello" << " World!"); example, you obtain an rvalue. foo() expects an lvalue reference to the stream. You might be able to get away with changing foo() to take an rvalue reference: std::ostream&&.

3 Comments

What temporary ostringstream?
@Praetorian: foo(std::ostringstream() << "Hello" << " World!"); though the ostream/ostringstream distinction is also relevant.
Oh, sorry, missed that first line. Anyway, his code sample doesn't have any such thing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.