Topic: String streams bound to a string


Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Wed, 21 Nov 2001 19:51:17 GMT
Raw View
Dietmar Kuehl wrote:
>
> Hi,
> Attila Feher wrote:
>
> > Would it make sense to have a standard stringstream (I guess only the
> > buffer implementation would need a change), which does not _have_ a
> > string but refers to one?
>
> No, it would not! The now deprecated strstream classes had functionality
> in a similar direction with the effect of causing all kinds of trouble.
[SNIP]

While I totally agree with the facts you wrote, not with the conclusions
you draw from them and show them up as facts.  If you think, that
professional C++ programmers could not handle a "streamshell" class for
strings than I would suggest that we also remove the C array support
from the language, the C strings definitely, since if they aren't 0
terminated they are deadly things... and I am afraid we must make
vectors range checked all the time!  Also make sure that dereferenced
end() iterators throw.  You would not believe me how many trouble I have
seen with addressing outside of a vector in several forms.

If you see my comments in the OP, you also see that there are 2 rules to
keep _only_, to avoid the "troubles' you have mentioned:
- once you have given the string to the refstream, it owns it.  You do
_not_ touch it.
- you do not delete or let of out scope the string before the stream is
done with it.

Now this (with any decent programmer) an easy requirement set, which is
simple to keep.  If you do not agree, please propose dropping auto_ptr,
too.  Since your code will fail as well, if you just delete the pointed
object _outside_ of auto_ptr.

So while I fully appreciate you taking time to answer, I would like to
tell you: I do not believe that this idea is as bad as you show it up
and it has to be addressed with this kind of (!hospitality).

As you have said, what is only needed is a special (BUT WELL DESIGNED)
stream buffer (and some typedefs).  Period.  Now I would rather like
_one_ definition of this than a seperate one at every team all around
the world who needed it.

BTW, I did not say I want to force this into the standard.  What I have
said is: it might be worth to think about this thing for a while.  With
facts and professional attitude.  This:

8<----Q
No, it would not! The now deprecated strstream classes had functionality
in a similar direction with the effect of causing all kinds of trouble.
Q---->8                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

is no fact.  I may say it is so far from technical fact, that it looks
much like politics to me.  It is a generality, and paralellism with
something totally different.  strstream classes handle C arrays.  We
talk about strings (encapsulated functionality) here.  Totally different
picture.

And this reads much like...  I wanted to write here a 3 letter word
(nothing slang), but just read it again how friendly is this and how
does it show up who is more important...:
8<----Q
I would be against this proposal and I think I have an effect on the
standard, although not necessary formally...
Q---->8

I did not threathen you in any ways.  But this sentence sounds like: I
do not like it, so it is better you give up even thinking about it,
because I will stop you, because I am the stronger...  Last time I have
met this kinda attitude in the... anyways...

I have no effect on the standard.  I definitely do not want to have bad
effect on the standard.  But I do ask you to please do _not_ stop other
people from thinking by sentences like the above, which means: you can
waste your time but regardless of what solution you present I will stop
it from succeeding due to my prejudice based on how strstream worked...

Or I am stupid. :-)))  I never rule out this possibility, but I do not
believe that I have deserved the style...

Attila

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Thu, 22 Nov 2001 17:34:21 GMT
Raw View
In article <3BF9FF94.136DE59@lmf.ericsson.se>, Attila Feher says...
>
>Michiel Salters wrote:

[SNIP]

>> std::string s;
>> std::stream2string(s) << "Hello" << ' ' << "world\n";
>> // see note[1] at bottom of post
>> std::stream2string(s) << std::clear << "Next string";
>>
>> std::streamstring would be function which creates an special iostream.
>> This object would have a type which can't be copied, and
>> you can't get the string out.
>[SNIP]

>That seems to be an easy, and clear idea!  Actually it solves several
>problems.  It came up in clc++m, but to solve another issue, and then I
>did not like the idea...  But putting it together like this:
>
>- it solves the temporaries cannot be bound to non-const references
>problem
>- provides a totally "invisible" implementation of the refstream,
>  therefore stopping people from fiddling
>  (is there a word like this? :-)  around with it
>- it makes the "transaction" of writing into the string totally closed.

>I wonder if this idea can be made exception safe to a good degree...  I
>mean _if_ you need total exception safety, you must fall back to
>ostringstream. :-)))  Since you need a _copy_ of the string to be
>modified, not the original, so that the original can stay unchanged
>_without_ any try/catch.

I don't think there is a fundamental exception-safety problem. Except for
the std::clear idea, the original string is not overwritten. Basically,
when constructing the stream you'd have to keep the original length, and
if anything throws, you reset the stream length and rethrow. Operator<<
typically doesn't modify its right hand side, so you can pretty much get
back where you started.

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Sat, 24 Nov 2001 01:54:15 GMT
Raw View
Attila Feher wrote:
...
> you draw from them and show them up as facts.  If you think, that
> professional C++ programmers could not handle a "streamshell" class for
> strings than I would suggest that we also remove the C array support
> from the language, the C strings definitely, since if they aren't 0
> terminated they are deadly things... and I am afraid we must make
> vectors range checked all the time!  Also make sure that dereferenced
> end() iterators throw.  You would not believe me how many trouble I have
> seen with addressing outside of a vector in several forms.


All of those things have been seriously proposed. If it weren't for
backward compatibility issues, I would even support some of those
suggestions (other than the checked array one).

...
> 8<----Q
> No, it would not! The now deprecated strstream classes had functionality
> in a similar direction with the effect of causing all kinds of trouble.
> Q---->8                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> is no fact.  I may say it is so far from technical fact, that it looks

I can't vouch for the truth of that claim, but it has the form of a
fact; it would be a fact if it's true. Are you claiming the ability to
prove that it's false?

...
> 8<----Q
> I would be against this proposal and I think I have an effect on the
> standard, although not necessary formally...
> Q---->8
>
> I did not threathen you in any ways.  But this sentence sounds like: I
> do not like it, so it is better you give up even thinking about it,
> because I will stop you, because I am the stronger...  Last time I have
> met this kinda attitude in the... anyways...

All that he's doing is emphasizing the degree to which he's sure of the
validity of his opinion. You're reading too much into it, if you take it
as any kind of threat.

...
> effect on the standard.  But I do ask you to please do _not_ stop other
> people from thinking by sentences like the above, which means: you can

People whose thought processes are so fragile that they can be stopped
by such sentences are unlikely to have useful, coherently presented
contributions to make.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Sat, 24 Nov 2001 01:54:48 GMT
Raw View
Michiel Salters wrote:
[SNIP]
> I don't think there is a fundamental exception-safety problem. Except for
> the std::clear idea, the original string is not overwritten. Basically,
> when constructing the stream you'd have to keep the original length, and
> if anything throws, you reset the stream length and rethrow. Operator<<
> typically doesn't modify its right hand side, so you can pretty much get
> back where you started.

Great idea.  I have never tought about it... of course.  We cannot clear
the screen, but we can simple restore the string...  But only if it is
not reallocated.  In which case iterators bye bye.  So strong exception
safety (am I mixing up them?) can only be made if the string is copied
first.

A

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Dietmar Kuehl <dietmar_kuehl@yahoo.com>
Date: Sat, 24 Nov 2001 01:55:17 GMT
Raw View
Hi,
Attila Feher wrote:

> While I totally agree with the facts you wrote, not with the conclusions
> you draw from them and show them up as facts.  If you think, that
> professional C++ programmers could not handle a "streamshell" class for
> strings than I would suggest that we also remove the C array support
> from the language, the C strings definitely, since if they aren't 0
> terminated they are deadly things... and I am afraid we must make
> vectors range checked all the time!  Also make sure that dereferenced
> end() iterators throw.  You would not believe me how many trouble I have
> seen with addressing outside of a vector in several forms.


Yes, access to C arrays should be restricted, C strings should be
banned, and container access should at least be optionally checked.
These things fall, however, into three different categories:
- The "streamshell" class you proposed is a new trap which should
   not be opened in the first place: A stated goal for the next round
   of standardization is to remove traps, not to add new ones.
- The C arrays and C strings are a legacy problem: There are good
   reasons why they should be removed but they would break too much of
   existing code. It is simply unrealistic to expect this to happen. This
   is a pretty unfortunate state of affairs but we are like to be stuck
   with these beasts. The best we can do is to educate people to avoid
   them in new code.
- Checking standard containers can be done under the hood and it is a
   a quality of implementation issue whether it is done or not. I think
   a good implementation would default to do checking and have, if
   necessary, some setup to remove checking for an optimized version.

I'd prefer to remove existing traps rather than to introduce new ones
in the next round of standardization. A major reason for this is my
experience when reviewing code of average C++ programmers: The code is
riddled with lots of little problems like misuses of built-in arrays
('T* a = new T[n]; ... delete a;'). Sure, I can't conclude from misuses
of built-in arrays to misuses of the "streamshell". There is no
argument by which follows that just because there is a common trap
exercised by many, sometimes even experienced, programmers this also
happens to a new trap. However, if there is no new trap at all, there
is also no danger for things like this to happen.

>
> If you see my comments in the OP, you also see that there are 2 rules to
> keep _only_, to avoid the "troubles' you have mentioned:
> - once you have given the string to the refstream, it owns it.  You do
> _not_ touch it.
> - you do not delete or let of out scope the string before the stream is
> done with it.


There is only one rule associated with releasing dynamically allocate
built-in arrays: Use 'delete[]', not 'delete'. Still, people get this
very simple rule wrong. Also, these two rules you mention are just two
more rules. If we have just one rule you have to remember, even if they
are natural to be followed in 90% of the cases, for each new class, we
should add not to many classes...


> Now this (with any decent programmer) an easy requirement set, which is
> simple to keep.  If you do not agree, please propose dropping auto_ptr,
> too.  Since your code will fail as well, if you just delete the pointed
> object _outside_ of auto_ptr.


Since 'std::auto_ptr' supports a bigger idiom which applies to more than
just 'std::auto_ptr' (RAII), it less of a problem. And although this is
IMO a lesser problem, I recommend against using 'std::auto_ptr'.

I also want to point out that there is a difference between adding
broken interfaces to the standard and removing broken interface which
are currently part of the standard: While the former can simply be
avoided in the first place, removal of the latter will break existing
code. I think it would be desirable to clean up C++ in various ways
which includes amoung others built-in arrays. This is, however, much
harder than avoiding new broken stuff.


> So while I fully appreciate you taking time to answer, I would like to
> tell you: I do not believe that this idea is as bad as you show it up
> and it has to be addressed with this kind of (!hospitality).


The idea of having a simple approach to add character to a string via a
stream interface is not bad at all and I don't think that I said
something like this. Just the approach to only define a new stream which
does only this is, IMO, bad and this is what I'm opposed to. In fact,
there was an alternative proposed in this thread which I would support
because it avoids the problems in the first place:

   string2stream(str) << foobar;

This approach is much harder to abuse and the rule which has to be
remembered to even close the potential for abuse is already in place
(namely not to return references to local variables).


> As you have said, what is only needed is a special (BUT WELL DESIGNED)
> stream buffer (and some typedefs).  Period.  Now I would rather like
> _one_ definition of this than a seperate one at every team all around
> the world who needed it.


The difference between a local class and a standard class is that it
requires the informed people locally to create the local class while the
standard class can be abused by everybody, including the uninformed
ones.

> And this reads much like...  I wanted to write here a 3 letter word
> (nothing slang), but just read it again how friendly is this and how
> does it show up who is more important...:
> 8<----Q
> I would be against this proposal and I think I have an effect on the
> standard, although not necessary formally...
> Q---->8
>
> I did not threathen you in any ways.  But this sentence sounds like: I
> do not like it, so it is better you give up even thinking about it,
> because I will stop you, because I am the stronger...


Since you kindly took my quote out of context, let me provide the
context again: You asked what people think of your proposal, especially
those people who are involved the standard. My answer consisted of two
parts:
1. I don't like this particular proposal.
2. I have an effect on the standard (not formally, as I mentioned, but
    people at least seem to listing to arguments I bring forward in
    discussions).

This is just an answer to your question: If you don't like a particular
answer to your question, don't ask the question. I'm not threating
anybody and I don't have the power to stop any proposal. I just voiced
that I would argue against it - you implied that I, not you, would be
heard.

> I have no effect on the standard.  I definitely do not want to have bad
> effect on the standard.  But I do ask you to please do _not_ stop other
> people from thinking by sentences like the above, which means: you can
> waste your time but regardless of what solution you present I will stop
> it from succeeding due to my prejudice based on how strstream worked...


You provided a solution to a problem which has, IMO, some problems. As

far as I remember I pointed out two particular problems I have with your
approach (life-time of the string and exact semantics of the insertion
in the context of additional accesses to the string). I would mention
these problems if your proposal would be discussed and I would argue
that these are severe problems which need to be addressed in some form.
Whether this means that people agree with me is an entirely different
issue. Someone else saw apparently similar problems and proposed an
approach how to address these: This is the goal in pointing out the
problems! I would not argue against a proposal where these problems are
removed (or at least made much more unlikely). I just failed to see the
solution to the problems I spotted myself, otherwise I would have posted
it myself.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Sat, 24 Nov 2001 01:55:26 GMT
Raw View
Michiel Salters wrote:
[SNIP]
> std::string s;
> std::stream2string(s) << "Hello" << ' ' << "world\n";
> // see note[1] at bottom of post
> std::stream2string(s) << std::clear << "Next string";
>
> std::streamstring would be function which creates an special iostream.
> This object would have a type which can't be copied, and
> you can't get the string out.
>
> E.g. ( ignoring obvious template params )
> namespace std {
> class __sstream : public iostream& { ... };
> __sstream stream2string( std::basic_string &s ) { ... }
> }
>
> Since the user can't copy it, etc. , the __sstream temporary used will
> be gone by the end of the full expression and the string updated. I
[SNIP]

Looking at this, looking at this and I have a doubt:

The __sstream returned by the function is an unnamed temporary object.
Now as far as I know, you cannot call a standalone operator<< for it:

ostream& operator<<( ostream&os...
                     ^^^^^^^^^^

This is a non-const reference, and cannot be bound to an unnamed
temporary.  Is this true?  So I am afraid your solution would not
compile with a standard conforming compiler.

I actually hate this, since an "outsider" operator<< is just the same
thing as a member.  So why can I call non-const members, but cannot call
operator<< ?  Not that it is an easy question to solve...

A

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Mon, 26 Nov 2001 17:27:45 GMT
Raw View
Dietmar Kuehl wrote:
[SNIP]
> You provided a solution to a problem which has, IMO, some problems. As
> far as I remember I pointed out two particular problems I have with your
> approach (life-time of the string and exact semantics of the insertion
> in the context of additional accesses to the string). I would mention
> these problems if your proposal would be discussed and I would argue
> that these are severe problems which need to be addressed in some form.
> Whether this means that people agree with me is an entirely different
> issue. Someone else saw apparently similar problems and proposed an
> approach how to address these: This is the goal in pointing out the
> problems! I would not argue against a proposal where these problems are
> removed (or at least made much more unlikely). I just failed to see the
> solution to the problems I spotted myself, otherwise I would have posted
> it myself.

Got the message.  I really have to find the machine making decaf. :-)

Anyways I have re-read my OP and I have found that I was not specific
enough to point out that I am looking for a solution to avoid those
traps myself.  Now the proposed idea of a functions, returning a
"streamshell" object seems to be very nice solution.  It avoids the
pitfalls of "whathappensif:string disappears;string is changed outside"
as well as "overcomes" the how-to-bind-to-nonconst-reference trouble (it
seems at least that op<< work nicely) as well as RVO should get rid off
the unneeded object.  So I love this solution myself and I do not see
any more troubles with it (just now).  But I am no guru.  Do you
(anyone) see a faulty point in the proposed "hiding" of the streamshell
class?

Here is the proposed solution:

Michiel Salters wrote:
8<----
E.g. ( ignoring obvious template params )
namespace std {
class __sstream : public iostream& { ... };
__sstream stream2string( std::basic_string &s ) { ... }
}
---->8

Of course we may want to have string2ostream, string2istream and
string2stream (I guess) to stay consistent.

Attila

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Mon, 26 Nov 2001 19:36:48 GMT
Raw View
In article <3BFD543E.FDF07AB2@lmf.ericsson.se>, Attila Feher says...
>
>Michiel Salters wrote:
>[SNIP]
>> I don't think there is a fundamental exception-safety problem. Except for
>> the std::clear idea, the original string is not overwritten. Basically,
>> when constructing the stream you'd have to keep the original length, and
>> if anything throws, you reset the stream length and rethrow. Operator<<
>> typically doesn't modify its right hand side, so you can pretty much get
>> back where you started.
>
>Great idea.  I have never tought about it... of course.  We cannot clear
>the screen, but we can simple restore the string...  But only if it is
>not reallocated.  In which case iterators bye bye.  So strong exception
>safety (am I mixing up them?) can only be made if the string is copied
>first.
>
>A

There's some balancing in how much exception safety you want, and how much
speed/how little code. A std:: function may understand the inner workings
of std::string, and know how much it can be done without copying. If a
resize is needed, the algorithm can first allocate the new memory, use that
to store the added characters from the stream, and only if that doesn't
throw, add the characters from the original string to the beginning of the
newly constructed string.

That's just the old trick of doing the things which could throw first, and
only after that do the things that can't be undone.

So you'd have something like

std::string s="Hello"; // allocates 5 bytes
std::stream2string(s) << " world\n";

The implementation would see that s needs to be resized, to 12 bytes. So
it allocates 12 bytes, stores the 7 new chars, then copies the original
5 chars, and only then deallocates the old 5 bytes. Looks like strong
exception safety, doesn't it?

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Sat, 17 Nov 2001 00:26:12 GMT
Raw View
In article <3BF35FA6.46BAA869@lmf.ericsson.se>, Attila Feher says...
>
>Hi All,
>
>Would it make sense to have a standard stringstream (I guess only the
>buffer implementation would need a change), which does not _have_ a
>string but refers to one?  My point is: with the current stringstream
>implementation one always must copy the result into a string, the
>starting value from a string...  Now suppose I place (for some reason) a
>large string into a string using a stringstream.  I pay significant
>price for vopying the result into a string.  I would say, with no good
>reason.
>
>My suggestions is to have a stringrefstream kinda standard stream, for
>which one gives a string to work on.  This basically can save a lot of
>CPU cycles and (I would say) makes the code more clean.  Of course, once
>I have passed this string (ref) to the
>ostringref_stream/istringrefstream/stringrefstream the "ownership" of
>the string (I mean the full control over its content) is passed as
>well.  So as long as the stream exists, you may only _read_ the string.
>Changing it _must_ be done via the streams' interface.

I think messing with a shared string without clearly defining real
ownership is a bad thing. Passing a std::shared_ptr<string> is much
cleaner. That saves you from a number of possible accidents.

Furthermore I think you might want to define clearer semantics. For
instance, is the underlying string updated even if you don't flush
the stream? The current stringstream might have an inefficiency due to
the copying, but it gives much easier semantics.

Regards,
Michiel Salters

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Sat, 17 Nov 2001 23:25:10 GMT
Raw View
Michiel Salters wrote:
[SNIP]
> I think messing with a shared string without clearly defining real
> ownership is a bad thing. Passing a std::shared_ptr<string> is much
> cleaner. That saves you from a number of possible accidents.

Ownership is clearly defined, probably I did not mention it clear
enough:

The string, as long as the stringrefstream exists (or not "disconnected"
if we want to support that) is owned by the refstream.  Noone else
should touch it.

And ownership also brings up lifetime Q.  The string must live at least
as long as the user refstream lives.  The refstream takes no
responsibility for the existence of the string, only the content.  The
content makes sense _only_ after the stream is destroyed, disconnected
(or flushed?).  While the stream owns the string it can only be written
via the refstream interface.  Reading is the same, except probably
immediately after a flush.  Reading and writing the string directly,
while it is connected to/owned by a refstream is undefined behaviour
(except probably flush-read).

> Furthermore I think you might want to define clearer semantics. For
> instance, is the underlying string updated even if you don't flush
> the stream?

Nope.  It must be effective.  It is meant to be a temporary stream shell
around a string.  It is not meant to be full featured wondestuff.  For
that one has stringstream.

> The current stringstream might have an inefficiency due to
> the copying, but it gives much easier semantics.

Which you may not need several times.  Esp. on your fast path.

I guess my semantics are not so complicated either.  refstream would be
a shell, which I could fast (CPU _and_ coding) put around a string, if I
need it as a stream.  When I need the string, I "open the shell and take
my perl". :-))  If you want to touch the perl before, the shell will
bite you (or byte?:-)

Attila

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl>
Date: Mon, 19 Nov 2001 16:54:27 GMT
Raw View
Sat, 17 Nov 2001 00:26:12 GMT, Michiel Salters <Michiel.Salters@cmg.nl> pisze:

> Passing a std::shared_ptr<string> is much cleaner.

Is it std::? I thought it's boost::.

--
 __("<  Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
 \__/
  ^^
QRCZAK

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Mon, 19 Nov 2001 16:55:55 GMT
Raw View
In article <3BF63BAB.F7306CA@lmf.ericsson.se>, Attila Feher says...
>
>Michiel Salters wrote:
>[SNIP]
>> I think messing with a shared string without clearly defining real
>> ownership is a bad thing. Passing a std::shared_ptr<string> is much
>> cleaner. That saves you from a number of possible accidents.
>
>Ownership is clearly defined, probably I did not mention it clear
>enough:
>
>The string, as long as the stringrefstream exists (or not "disconnected"
>if we want to support that) is owned by the refstream.  Noone else
>should touch it.
>
>And ownership also brings up lifetime Q.  The string must live at least
>as long as the user refstream lives.  The refstream takes no
>responsibility for the existence of the string, only the content.  The
>content makes sense _only_ after the stream is destroyed, disconnected
>(or flushed?).  While the stream owns the string it can only be written
>via the refstream interface.  Reading is the same, except probably
>immediately after a flush.  Reading and writing the string directly,
>while it is connected to/owned by a refstream is undefined behaviour
>(except probably flush-read).
>
>> Furthermore I think you might want to define clearer semantics. For
>> instance, is the underlying string updated even if you don't flush
>> the stream?
>
>Nope.  It must be effective.  It is meant to be a temporary stream shell
>around a string.  It is not meant to be full featured wondestuff.  For
>that one has stringstream.
>
>I guess my semantics are not so complicated either.  refstream would be
>a shell, which I could fast (CPU _and_ coding) put around a string, if I
>need it as a stream.  When I need the string, I "open the shell and take
>my perl". :-))  If you want to touch the perl before, the shell will
>bite you (or byte?:-)
>
>Attila

I still don't like the possibilities of undefined behavior abound.
If the original string owner still has access to the string,
accidents are bound to happen. Bjarne is pointing out quite often
that the language already offers too many traps for novices.

Perhaps we should have a class stream2string with semantics to allow

std::string s;
std::stream2string(s) << "Hello" << ' ' << "world\n";
// see note[1] at bottom of post
std::stream2string(s) << std::clear << "Next string";

std::streamstring would be function which creates an special iostream.
This object would have a type which can't be copied, and
you can't get the string out.

E.g. ( ignoring obvious template params )
namespace std {
class __sstream : public iostream& { ... };
__sstream stream2string( std::basic_string &s ) { ... }
}

Since the user can't copy it, etc. , the __sstream temporary used will
be gone by the end of the full expression and the string updated. I
think this idea in concept is more bulletproof; that is, it would be
harder to break. Having a global std::string in which some operator<<
is writing as a side effect, and then passing that to stream2string
would still break things, of course.

Would these cover your needs ?

--- notes ---
[1] std::clear might actually make sense for a number of existing
iostreams as well. Of course, it can't work on just any ostream&,
and therefore couldn't appear in the middle of a << sequence,
but the first argument of a << sequence usually has access to the
final type (e.g. ofstream& instead of ostream& ).

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Tue, 20 Nov 2001 18:06:51 GMT
Raw View
Marcin 'Qrczak' Kowalczyk wrote:
>
> Sat, 17 Nov 2001 00:26:12 GMT, Michiel Salters <Michiel.Salters@cmg.nl> pisze:
>
> > Passing a std::shared_ptr<string> is much cleaner.
>
> Is it std::? I thought it's boost::.

I guess we should take it as a hint :-)

A

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Tue, 20 Nov 2001 18:06:49 GMT
Raw View
Michiel Salters wrote:
[SNIP]
> >Nope.  It must be effective.  It is meant to be a temporary stream shell
> >around a string.  It is not meant to be full featured wondestuff.  For
> >that one has stringstream.
[SNIP]
> I still don't like the possibilities of undefined behavior abound.
[SNIP]
> Perhaps we should have a class stream2string with semantics to allow
>
> std::string s;
> std::stream2string(s) << "Hello" << ' ' << "world\n";
> // see note[1] at bottom of post
> std::stream2string(s) << std::clear << "Next string";
>
> std::streamstring would be function which creates an special iostream.
> This object would have a type which can't be copied, and
> you can't get the string out.
[SNIP]
> Would these cover your needs ?

That seems to be an easy, and clear idea!  Actually it solves several
problems.  It came up in clc++m, but to solve another issue, and then I
did not like the idea...  But putting it together like this:

- it solves the temporaries cannot be bound to non-const references
problem
- provides a totally "invisible" implementation of the refstream,
therefore stopping people from fiddling (is there a word like this? :-)
around with it
- it makes the "transaction" of writing into the string totally closed.

I wonder if this idea can be made exception safe to a good degree...  I
mean _if_ you need total exception safety, you must fall back to
ostringstream. :-)))  Since you need a _copy_ of the string to be
modified, not the original, so that the original can stay unchanged
_without_ any try/catch.

Attila

> --- notes ---
> [1] std::clear might actually make sense for a number of existing
> iostreams as well. Of course, it can't work on just any ostream&,
> and therefore couldn't appear in the middle of a << sequence,
> but the first argument of a << sequence usually has access to the
> final type (e.g. ofstream& instead of ostream& ).

Makes sense!

Attila

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: Thu, 15 Nov 2001 16:57:24 GMT
Raw View
Hi All,

Would it make sense to have a standard stringstream (I guess only the
buffer implementation would need a change), which does not _have_ a
string but refers to one?  My point is: with the current stringstream
implementation one always must copy the result into a string, the
starting value from a string...  Now suppose I place (for some reason) a
large string into a string using a stringstream.  I pay significant
price for vopying the result into a string.  I would say, with no good
reason.

My suggestions is to have a stringrefstream kinda standard stream, for
which one gives a string to work on.  This basically can save a lot of
CPU cycles and (I would say) makes the code more clean.  Of course, once
I have passed this string (ref) to the
ostringref_stream/istringrefstream/stringrefstream the "ownership" of
the string (I mean the full control over its content) is passed as
well.  So as long as the stream exists, you may only _read_ the string.
Changing it _must_ be done via the streams' interface.

I know, bad programmers may create bad code by passing a string which
goes out of existence before the stream does.  However (since it should
take a non-const reference as a constructor argument) it would not be
easy to do it anyways.

Pros: clearer code, the stream works clearly into/from/using the string
it gets.  Saves CPU cycles as well.
Cons: stringrefstreams cannot exist on their own:
- they will either have no default constructor
  (cannot create array of them etc.)
- or they will need a pointer inside not
  a reference to the string, but this bring new trouble:
  - we either need to check inside _every_ call
    using the buffer that the pointer is not NULL.
    In such case a new exception should also be
    introduced to indicate the use of an
    "empty" stringstream;
  - or we can declare the use of an "empty" stringrefstream
    in the standard the same way the indirection of a NULL
    pointer is.  Basically it would be a kind of "added value
    pointer" anyways.

I will post also to comp.lang.c++.moderated about class->string
conversions and the dreaded stringstream.  If you want to know why do I
think this refstream is needed, please read that, too.

Opinions?  Do you like it?  Someone who actually has effect on the
standard? :-)  Herb? :-)

Attila

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Dietmar Kuehl <dietmar_kuehl@yahoo.com>
Date: Sat, 17 Nov 2001 00:00:32 GMT
Raw View
Hi,
Attila Feher wrote:

> Would it make sense to have a standard stringstream (I guess only the
> buffer implementation would need a change), which does not _have_ a
> string but refers to one?


No, it would not! The now deprecated strstream classes had functionality
in a similar direction with the effect of causing all kinds of trouble.
If someone really needs the optimization which I consider quite
unlikely, eg. because the string typically processed are small a custom
stream buffer class is easily written! For example:

   struct stringrefbuf: std::streambuf {
     stringrefbuf(std::string& str): m_str(str) {}
   private:
     int overflow(int c) {
       if (traits_type::eq_int_type(c, traits_type::eof())
         return traits_type::not_eof(c);
       m_str.push_back(traits_type::to_char_type(c));
       return c;
     }
     std::string& m_str;
   };
   struct stringrefstreamaux {
     stringrefstreamaux(std::string& str): m_sbuf(str) {}
     stringrefbuf m_sbuf;
   };
   class ostringrefstream:
     virtual stringrefstreamaux, public std::ostream {
     ostringrefstream(std::string& str):
       stringrefstreamaux(str),
       std::ostream(&m_sbuf) {}
   };

Most of this stuff is trivial code just passing around ctor arguments.
The net effect is probably, that you end up with something which is
slower than string streams, however... The reason for this is that
characters need to be inserted individually into the stream to assure
that the external string has a consistent state with the insertions
into the stream. However, you can freely modify the string because
the stream does not really depend on the string's state. Requiring
that you call something like 'pubsync()' on the stream buffer before
accessing the string (or 'flush()' on the corresponding buffer or
whatever your favorite method of effectively calling 'pubsync()'
looks like) make the interface even worse than it already is due to
referencing an object which may accidentally go out of scope.

To just hack up a stream buffer which does the job at hand in a
sensible way seems the right approach to address any performance
problems in this area. In particular you can use different internal
approaches, too, like eg. buffering or providing a string of an
appropriate size.

I would be against this proposal and I think I have an effect on the
standard, although not necessary formally...
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]