Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

why can't you copy stringstream?

67 views
Skip to first unread message

Vir Campestris

unread,
Jul 20, 2017, 4:58:54 PM7/20/17
to
Subject says it all.

I can see why you couldn't copy a file stream, but a stringstream is
just a buffer and some pointers - yet copying is forbidden.

Anyone know why?

(I just wrapped it for my use, where as it happens I only copy it empty
- it's part of a complex object)

Andy

Öö Tiib

unread,
Jul 20, 2017, 5:54:38 PM7/20/17
to
It is because it is stream, copying it does not make sense like
copying file descriptor or hard drive or thread does not make sense.

What really matters in it is its streambuf. Let me demonstrate that
a bit by screwing with our favorite, std::cout. ;)

#include <iostream>
#include <sstream>

int main()
{
std::stringstream ss;
std::streambuf *coutbuf = std::cout.rdbuf();
std::cout.rdbuf(ss.rdbuf());
std::cout << "second text" << std::endl;
std::string s = ss.str();
std::cout.rdbuf(coutbuf);
std::cout << "first text : " << s;
}

What it outputs to console?
Hope you start to get the idea why copying streams does not make sense.

Richard

unread,
Jul 20, 2017, 6:56:11 PM7/20/17
to
[Please do not mail me a copy of your followup]

Vir Campestris <vir.cam...@invalid.invalid> spake the secret code
<okr5ad$t8e$2...@dont-email.me> thusly:

>I can see why you couldn't copy a file stream, but a stringstream is
>just a buffer and some pointers - yet copying is forbidden.
>
>Anyone know why?

Liskov Substitution Principle
<https://en.wikipedia.org/wiki/Liskov_substitution_principle>

The base class is not copyable (std::ostream/std::istream/std::iostream)
therefore a derived class cannot change this part of the contract and
honor LSP.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Alf P. Steinbach

unread,
Jul 20, 2017, 9:37:30 PM7/20/17
to
On 21.07.2017 00:56, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Vir Campestris <vir.cam...@invalid.invalid> spake the secret code
> <okr5ad$t8e$2...@dont-email.me> thusly:
>
>> I can see why you couldn't copy a file stream, but a stringstream is
>> just a buffer and some pointers - yet copying is forbidden.
>>
>> Anyone know why?
>
> Liskov Substitution Principle
> <https://en.wikipedia.org/wiki/Liskov_substitution_principle>
>
> The base class is not copyable (std::ostream/std::istream/std::iostream)
> therefore a derived class cannot change this part of the contract and
> honor LSP.
>

struct Foo{ virtual void x() = 0; };
struct Bar: Foo { void x() override {} };

Works fine for me.

Disclaimer: code not touched by compiler.


Cheers!,

- Alf



Gareth Owen

unread,
Jul 21, 2017, 1:58:09 AM7/21/17
to
legaliz...@mail.xmission.com (Richard) writes:

> Liskov Substitution Principle
> <https://en.wikipedia.org/wiki/Liskov_substitution_principle>
>
> The base class is not copyable (std::ostream/std::istream/std::iostream)
> therefore a derived class cannot change this part of the contract and
> honor LSP.

I don't buy this argument at all.

Why is "not copyable" an intrinsic part of an LSP contract and "doesn't
have a clone() method" not? That seems rather too tied up in how C++
works to be part of any kind of principle.

Jerry Stuckle

unread,
Jul 21, 2017, 8:44:59 AM7/21/17
to
The base class is part of the derived class. In order to copy the
derived class, the base class must also be copyable.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Richard

unread,
Jul 21, 2017, 11:29:12 AM7/21/17
to
[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
<okrlkn$fi4$1...@dont-email.me> thusly:
What you wrote above *is* adherence to LSP.

I don't see any use of std::{i,o,io}stream here. Are you saying those
are copyable? Because I thought they were not.

Yes, basic_{i,o}stream is not copyable, its copy constructor is deleted in
C++11:

<http://en.cppreference.com/w/cpp/io/basic_istream/basic_istream>
<http://en.cppreference.com/w/cpp/io/basic_ostream/basic_ostream>

It can be moved, but not copied.

Vir Campestris

unread,
Jul 23, 2017, 4:42:01 PM7/23/17
to
cout isn't a stringstream, it's a file. A funny file, but still a file.

When I write something into a stringstream it is stored in its internal
buffer until I get around to pulling it out. A copy I'd expect to have
its own buffer, containing the same data.

You can't do that with a file.

So to me it makes perfect sense not to be able to copy cout - or any
other file based stream - but to be able to copy stringstream.

Andy

Öö Tiib

unread,
Jul 23, 2017, 6:25:00 PM7/23/17
to
In what sense of "file"?
The std::cout is ostream of unspecified nature and usually it is
directed to standard output of program (that might be sometimes piped into
a file). However I posted code above how cout can easily go into buffer
of stringsteam (and to share it) as well.

>
> When I write something into a stringstream it is stored in its internal
> buffer until I get around to pulling it out. A copy I'd expect to have
> its own buffer, containing the same data.
>
> You can't do that with a file.
>
> So to me it makes perfect sense not to be able to copy cout - or any
> other file based stream - but to be able to copy stringstream.

I don't understand how it makes sense to copy a stream but may be in
your problem domain it somehow makes sense. Still std::strinstream
copy constructor is "= delete;" so you can't anyway use it.

If you want a stream with copied buffer content then you can make one.
It is not too hard:

std::stringstream ss_2(ss_1.str(), std::ios_base::out|std::ios_base::ate);

Done.

Richard

unread,
Jul 24, 2017, 1:06:55 PM7/24/17
to
[Please do not mail me a copy of your followup]

Vir Campestris <vir.cam...@invalid.invalid> spake the secret code
<ol31en$e2s$2...@dont-email.me> thusly:

>So to me it makes perfect sense not to be able to copy cout - or any
>other file based stream - but to be able to copy stringstream.

Technically you're not copying the stringstream (no copy constructor
is invoked and no assignment operator is invoked in the given code
snippet). You're using an extra member function of stringstream (str)
to obtain a copy of its internal buffer.
0 new messages