Topic: COW strings banned because of exceptions? was: Vindicated? Sutter
Author: kanze@gabi-soft.fr
Date: Wed, 15 Sep 2004 20:13:18 +0000 (UTC) Raw View
Herb Sutter <hsutter@gotw.ca> wrote in message
news:<j9pek0tqmqmlrc8e7nac45loa3vvk1sadn@4ax.com>...
> On 14 Sep 2004 08:22:11 -0400, David Abrahams
> <dave@boost-consulting.com> wrote:
> >Herb Sutter <hsutter@gotw.ca> writes:
> > > Finally, it's worth noting that std::string has even more
> > > constraints for COW than you or I have mentioned here, and that
> > > are entirely unrelated to thread safety. In particular, it's not
> > > clear to me how any COW implementation of std::string can be
> > > standards-conforming because of this situation (which I've been
> > > pointing out for years in hallway conversations and talks, but it
> > > now occurs to me I don't think I've written about):
> > > string s1( "Hello" );
> > > string s2( s1 );
> > > According to the standard, I don't believe a conforming
> > > implementation may do a shallow copy here. The reason is that
> > > there's no way to know whether the very next use of the string
> > > will mention op[]:
> > > s1[0]; // or, s2[0]
> > > If string did use COW and did a shallow copy when constructing s2,
> > > then str[0] must do a deep copy, which means it will allocate
> > > memory, which means it could throw a bad_alloc exception, and that
> > > is nonconforming because when the index is within bounds no
> > > exception may be thrown.
> >Since when? Standard references please!
> >I think there may be reasons that a conforming COW string is
> >impossible, but this ain't one of them, AFAICT.
> Ah, I forgot string []/at mirrored vector's. (We must fix that, but
> that's a separate issue.) So just change [] to at:
> s1.at(0); // or, s2.at(0)
Note that neither operator[] nor at() have exception specifiers in my
copy of the standard (the 1998 version).
> Now it's clear that the above is not allowed to throw,
Even considering the second sentence in 17.4.4.8/3: "Any other
functions [than a destructor] defined in the C++ Standard Library that
do not have an exception-specification may throw implementation-defined
exceptions unless otherwise specified."
> but could do so on a COW implementation.
> For those keeping score at home, this is because of wording in the
> standard that Dave himself was instrumental in crafting:
> 17.4.4.8(1)
> Any of the functions defined in the C + + Standard Library can
> report a failure by throwing an exception of the type(s) described
> in their Throws: paragraph and/or their exception-specification
> (15.4). An implementation may strengthen the exception-
> specification for a non-virtual function by removing listed
> exceptions. 175)
> Footnote 175:
> That is, an implementation of the function will have an explicit
> exception-specification that lists fewer exceptions than those
> specified in this International Standard. It may not, however,
> change the types of exceptions listed in the exception-
> specification from those specified, nor add others.
> In short, the standard library, any operation with a "Throws:"
> paragraph may throw only listed exceptions.
That's not quite what the text you quote says. Although the first
sentence speaks of "their Throws: paragraph and/or their
exception-specification", the others only say
"exception-specification". And neither operator[] nor at() have an
exception specification.
I don't know if this is a defect in the standard, or whether it was
intentional. One can easily imagine that the authors really intended to
cover three cases:
- No specifications as to what happens on implementation defined
errors -- the function has neither a throws clause nor an exception
specification. (This is the most common cases.)
- The standard specifies exactly and fully all possible exceptions:
the function has an exception specification (and probably a throws
clause as well).
- The standard specifies precise exceptions for certain types of
errors, but leaves the implementation free, as in the first case,
for all other possible errors: the function has a throws clause, but
no exception specification.
Unless there is a defect report on this, I'd say that the most probable
intention was to allow the three cases, and that at() falls into the
third -- an illegal index throws a well defined exception, but an
implementation is free to throw an implementation defined exception.
(IMHO, footnote 178 seems to confirm this interpretation.)
As far as I can see, something like:
template< typename CharT >
std::basic_string< CharT >::const_reference
std::basic_string< CharT >::at() const
{
throw 3.14159 ;
}
is a perfectly conforming implementation. Not a very useful one, of
course, but the standard doesn't require usefulness.
If you think that this is a misinterpretation of the standard, please
explain why.
If you think that it is a defect, or at least, something we should
change, I'm behind you 100%. It means that in theory, at least, it is
impossible to write exception safe code without depending on
implementation defined behavior. (Note, for example, that
std::string::swap doesn't have an exception specification either.)
> For basic_string<>::at, we have:
> 21.3.4(3):
> Throws: out_of_range if pos >= size().
> That is, at may not throw an exception of any type besides
> out_of_range, and it may throw no exceptions if pos < size().
All that says is that basic_string<>::at MUST throw the designated
exception for this particular error. The paragraph you quote says that
a function "can" report an error by means of the specified exception.
It does not say that it "shall not" raise any other exceptions.
(On rereading it: I don't like the use of "can" either. Normally,
requirements on an implementation use the verb "shall". I would much
prefer text which clearly required an implementation to report errors
decribed in the Throws: clause by means of the described exception, or
one derived from it. I rather think that this was the intent, but my
interpretation of "can", in the context of the standard, is that an
implementation is allowed to, but not required to.)
At any rate, I've changed the subject, and added comp.std.c++ to the
groups, since this really has nothing to do with your implementation of
COW strings. (I'd also have set followups if my newsreader allowed it.)
> That being the case here, COW cannot be a conforming implementation of
> std::string AFAICS because of the given sequence:
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[ 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.jamesd.demon.co.uk/csc/faq.html ]