Difference between initializations stringstream.str( a_value ) and stringstream << a_value

c++, concatenation, initialization, stringstream

Solution

The problem you're experiencing is because `std::stringstream` is constructed by default with `ios_base::openmode mode = ios_base::in|ios_base::out` which is a non-appending mode.

You're interested in the output mode here (ie: `ios_base::openmode mode = ios_base::out`)

`std::basic_stringbuf::str(const std::basic_string<CharT, Traits, Allocator>& s)` operates in two different ways, depending on the `openmode`:

`mode & ios_base::ate == false`: (ie: non-appending output streams):

`str` will set `pptr() == pbase()`, so that subsequent output will overwrite the characters copied from s

`mode & ios_base::ate == true`: (ie: appending output streams):

`str` will set `pptr() == pbase() + s.size()`, so that subsequent output will be appended to the last character copied from s

(Note that this appending mode is new since c++11)

More details can be found here.

If you want the appending behaviour, create your `stringstream` with `ios_base::ate`:

std::stringstream ss(std::ios_base::out | std::ios_base::ate)

Simple example app here:

#include <iostream>
#include <sstream>

void non_appending()
{
    std::stringstream ss;
    std::string s = "hello world";

    ss.str(s);
    std::cout << ss.str() << std::endl;

    ss << "how are you?";
    std::cout << ss.str() << std::endl;
}

void appending()
{
    std::stringstream ss(std::ios_base::out | std::ios_base::ate);
    std::string s = "hello world";

    ss.str(s);
    std::cout << ss.str() << std::endl;

    ss << "how are you?";
    std::cout << ss.str() << std::endl;
}

int main()
{
    non_appending();
    appending();

    exit(0);
}

This will output in the 2 different ways as explained above:

hello world
how are you?
hello world
hello worldhow are you?

Problem

Consider: ``` std::string s_a, s_b; std::stringstream ss_1, ss_2; // at this stage: // ss_1 and ss_2 have been used and are now in some strange state // s_a and s_b contain non-white space words ss_1.str( std::string() ); ss_1.clear(); ss_1 << s_a; ss_1 << s_b; // ss_1.str().c_str() is now the concatenation of s_a and s_b, // <strike>with</strike> without space between them ss_2.str( s_a ); ss_2.clear(); // ss_2.str().c_str() is now s_a ss_2 << s_b; // line *** // ss_2.str().c_str() the value of s_a is over-written by s_b // // Replacing line *** above with "ss_2 << ss_2.str() << " " << s_b;" // results in ss_2 having the same content as ss_1. ``` Questions: What is the difference between stringstream.str( a_value ); and stringstream << a_value; and, specifically, why does the first not allow concatenation via << but the second does? Why did ss_1 automatically get white-space between s_a and s_b, but do we need to explicitly add white space in the line that could replace line ***: `ss_2 << ss_2.str() << " " << s_b;`?

Original source