Discussion:
why can't you copy stringstream?
(too old to reply)
Vir Campestris
2017-07-20 20:58:37 UTC
Permalink
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
2017-07-20 21:54:17 UTC
Permalink
Post by Vir Campestris
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)
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.
Vir Campestris
2017-07-23 20:41:45 UTC
Permalink
Post by Öö Tiib
Post by Vir Campestris
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)
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.
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
2017-07-23 22:24:41 UTC
Permalink
Post by Vir Campestris
Post by Öö Tiib
Post by Vir Campestris
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)
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.
cout isn't a stringstream, it's a file. A funny file, but still a file.
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.
Post by Vir Campestris
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.
legalize+ (Richard)
2017-07-24 17:06:38 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Vir Campestris
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.
--
"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>
legalize+ (Richard)
2017-07-20 22:56:01 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Vir Campestris
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
2017-07-21 01:37:09 UTC
Permalink
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by Vir Campestris
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
legalize+ (Richard)
2017-07-21 15:28:52 UTC
Permalink
[Please do not mail me a copy of your followup]
Post by Alf P. Steinbach
Post by legalize+ (Richard)
[Please do not mail me a copy of your followup]
Post by Vir Campestris
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.
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.
--
"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>
Gareth Owen
2017-07-21 05:57:50 UTC
Permalink
Post by legalize+ (Richard)
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
2017-07-21 12:45:30 UTC
Permalink
Post by Gareth Owen
Post by legalize+ (Richard)
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.
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
***@attglobal.net
==================
Loading...