Is it possible to change ostringstream rdbuf?
Asked Answered
C

2

6

I try the following code:

ostringstream oss;

streambuf *psbuf, *backup;

backup = oss.rdbuf();     
psbuf = cout.rdbuf();        
oss.rdbuf(psbuf);        
oss << things << endl;
oss.rdbuf(backup);   

But unfortunately I get this error:

error: too many arguments to function call, expected 0, have 1
    oss.rdbuf(backup);   

But rdbuf has two overloads:

get (1) basic_streambuf<char_type,traits_type>* rdbuf() const;

set (2) basic_streambuf<char_type,traits_type>* rdbuf (basic_streambuf<char_type,traits_type>* sb);

Yes I know it says basic_streambuf but it really is just a typedef typedef basic_streambuf<char> streambuf;, so it should work. Why is it not working?

Cradlesong answered 7/3, 2014 at 6:35 Comment(0)
S
7

Even though std::ostringstream inherits rdbuf from std::basic_ios that overload will not be accessible due to the fact that std::basic_ostream also defines its own member-function named rdbuf, effectively hiding the overload(s) you are looking for.

You can get access to the member-function by casting your std::ostringstream instance to a std::ostream reference as in the below example:

std::ostringstream oss;
std::ostream&      oss_ref = oss;

auto prev = oss_ref.rdbuf (std::cout.rdbuf ());

oss << "hello world"; // will print to the buffer of std::cout

oss_ref.rdbuf (prev); // reset

static_cast<std::ostream&> (oss).rdbuf (...) // equivalent

Why does std::basic_ostringstream define its own rdbuf?

Normally rdbuf returns a std::basic_streambuf* but std::ostringstream uses a std::basic_stringbuf.

Since one cannot overload based on return-type a decision was made to effectively hide the former overload in favour of the new one.

By returning a std::basic_stringbuf it's easy to see that std::ostringstream uses a stringbuf internally, and it also provides easier access to the str functions of std::basic_stringbuf (functions which doesn't exist in std::basic_streambuf).

Sera answered 7/3, 2014 at 7:30 Comment(1)
Why doesn't basic_ostringstream also define another rdbuf(basic_stringbuf*)?Tweedy
T
0

Because in the class ostringstream (typedef of basic_ostringstream<char>), only the gettor version of rdbuf() was defined as its member function, so the settor version inheriting from base class was hided. You can use the settor version of rdbuf() by upcasting oss to the base class such as ostream.

Tweedy answered 7/3, 2014 at 7:24 Comment(1)
I'm also puzzled by why ostringstream was designed by this way?Tweedy

© 2022 - 2024 — McMap. All rights reserved.