2

Given one stringstream object, I would like to copy it to another. According to :

how copy from one stringstream object to another in C++?

(among others), the proper way to do this is to use the rdbuf() member. However, this seems to cause issues, particularly if the stringstream is const.

For example:

void DoSomething(stringstream & ss)
{
    stringstream sstmp;

    cout << "pos 1: " << ss.tellg() << "\n";
    sstmp << ss.rdbuf();
    cout << "pos 2: " << ss.tellg() << "\n";
//        sstmp.rdbuf()->pubseekpos(0, ios_base::in | ios_base::out);

    cout << "String: " << sstmp.str() << "\n";
}

int main(void)
{
    stringstream ss;
    ss << "Hello";

    DoSomething(ss);
    DoSomething(ss);

    return 0;
}

The output is

pos 1: 0
pos 2: 5
String: Hello
pos 1: 5
pos 2: 5
String: 

The first call to DoSomething() changed the internal pointer, and seems to do so even if the stringstream is const (left out here as even tellg() is not const). The way to remedy this is with seekg(), but that can't be called on const streams. I attempted another way (commented out in the code) but without success.

So what can be done to either:

  1. Copy a (const) stringstream without really changing it, or

  2. reset the position on a const object?

Note: Compiled using gcc 4.8.1 on Arch Linux

Community
  • 1
  • 1
Benjamin Pritchard
  • 915
  • 2
  • 8
  • 15
  • Losing the `tellg()` calls and adding a call to `ss.rdbuf()->pubseekoff(0, std::ios_base::beg, std::ios_base::in);` will likely get what you want, but I'm not sure it will drive home what is the real question for me; why. Someone with deeper understanding of the stream lib will have to step in. Great question, and +1 for doing the initial homework on prospective answers. – WhozCraig Jul 11 '13 at 17:12

1 Answers1

1

The straightforward way is to just make the string and copy that way: sstmp.str(ss.str());

The less obvious approach is to fully utilize the fact that you can gain non-const access to the rdbuf from a const stringstream.

I made several changes so your code compiles, and updated the code to directly set the rdbuf's position, but it should do what you want, now outputting:

String: Hello
String: Hello

-

#include <sstream>
#include <iostream>

void DoSomething(const std::stringstream& ss)
{
    std::stringstream sstmp;

    sstmp << ss.rdbuf();
    ss.rdbuf()->pubseekpos(0, std::ios_base::in);

    std::cout << "String: " << sstmp.str() << "\n";
}

int main()
{
    std::stringstream ss;
    ss << "Hello";

    DoSomething(ss);
    DoSomething(ss);

    return 0;
}
Mark B
  • 95,107
  • 10
  • 109
  • 188