Benjamin Pritchard
Benjamin Pritchard

Reputation: 985

C++ Stringstream - copying with rd_buf changes const object

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

Upvotes: 2

Views: 387

Answers (1)

Mark B
Mark B

Reputation: 96281

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;
}

Upvotes: 1

Related Questions