From: Bo Persson on
Kenneth 'Bessarion' Boyd wrote:
> On Jul 26, 12:45 pm, Mathias Gaunard <loufo...(a)gmail.com> wrote:
>
>> It is fairly trivial to write a wrapper of std::vector<T>::insert
>> for example that provides strong exception safety, so I don't see
>> what you mean by "there is NO WAY" to do it.
>
>> Technique is simple: build another temporary vector, then if all
>> went well swap (which is nothrow). That technique can be virtually
>> applied in all cases you'd want to make a primitive strongly
>> exception-safe.
>
> At least for C++0X, std::vector<T>::insert is the only insert member
> function that requires fixing. All of the others are required to at
> least satisfy the strong exception guarantee
> anyway([container.requirements.general]/11, plus tracing all four
> listed exemptions to that). However, per [vector.modifiers]/1
> simply doing the insert on the copy and then swapping is not
> required to make a uniformly strongly exception-safe wrapper for
> std::vector<T>::insert : we have unspecified behavior for an
> exception- throwing move constructor of a type that is not
> copy-constructible.
> Is the intent there that the strong exception guarantee on such a
> move constructor will prevent the unspecified behavior?
>

It is a limitation on what you can put into a vector. If the move
constructor throws during a multi element move, we might have lost
some originals and are not assured that they can be restored (beacuse
a move back might throw as well). To avoid that, the implementation
will instead copy Ts internally, and destroy the originals only after
the operation is complete.

However, if the T doesn't even have a copy constructor we are screwed.
That's undefined behavior. You avoid this by just not putting that
kind of Ts into a vector, or at least not in a way so that they have
to be relocated (using reserve might help).


Bo Persson



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Jul 27, 3:43 pm, "Kenneth 'Bessarion' Boyd" <zaim...(a)zaimoni.com>
wrote:
> On Jul 26, 11:40 pm, Mathias Gaunard <loufo...(a)gmail.com> wrote:
>
> > On Jul 26, 11:48 pm, "Kenneth 'Bessarion' Boyd" <zaim...(a)zaimoni.com>
> > wrote:
>
> > > However, per [vector.modifiers]/1 simply
> > > doing the insert on the copy and then swapping is not required to make
> > > a uniformly strongly exception-safe wrapper for
> > > std::vector<T>::insert : we have unspecified behavior for an exception-
> > > throwing move constructor of a type that is not copy-constructible.
>
> > What move constructor are you talking about?
> > That of the allocator?
>
> The one referenced there: T's.

Oh sorry, the way you wrote it was confusing.
If T is not copy-constructible, then you can't copy the vector in the
first place, so you can't apply the technique at all.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Jul 27, 10:39 pm, Joshua Maurice <joshuamaur...(a)gmail.com> wrote:
> On Jul 27, 7:46 am, Mathias Gaunard <loufo...(a)gmail.com> wrote:
>
> > On Jul 27, 5:35 am, n...(a)cam.ac.uk wrote:
> >> In C++, a signal handler can raise an exception - that generates
> >> an asynchronous exception.
>
> > Standard C++ has no notion of signals either.
>
> What? A quick search of the C++03 standard shows otherwise.

My bad. Was always persuaded it was purely a POSIX feature, but it
seems ANSI C had it indeed.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Joshua Maurice on
On Jul 27, 2:13 pm, Michael Kilburn <crusader.m...(a)gmail.com> wrote:
> Anyway -- since I am reading standard on regular basis, my point was
> to find these guarantees there. Which is turned out to be non-trivial
> task -- whoever was documenting these definitely did not want anyone
> to find them out... Even though Daniel cleared some fog for me
> (thanks!), it seems there are still black holes in standard with
> respect to this.

I agree this is a serious problem. I suspect it's due to the nature of
the international standardization process. It's quite refreshing to
read the Java standard as compared to the C++ standard. It's an
entirely different approach to standard writing. The Java standard is
amazingly clear, and it cuts right to the issues. The C++ standard is
amazingly unclear.

For example, I cannot tell if the standard allows me to read and write
to POD types through an unsigned char pointer. It seems to hint at
this quite strongly in various passages, but nowhere does it come out
and say that you can. The only confirmed thing I can find is memcpy.

I wish that the C++ standard was more concise. I wish it was more
clear in saying "Yes you can" and "No you cannot" on important issues.
Ex: the unsigned char pointer POD type thing, "A complete object
allocated on the stack, via placement new, or via regular new, exists
in a contiguous chunk of memory of sizeof(the_type) bytes" or
explicitly call out that this observable "guarantee" can be violated,
etc. There are plenty of dark corners of the standard where intent is
less than clear and the actual requirements of the standard are so
vague as to be undecidable. It should be possible (even easy!) for any
professional to answer "Is this program ill-formed?", "Does this
program have undefined behavior?", etc. This is definitely not the
case today.

For the exception guarantees, I wish that the requirements for what
operations would be cleaned up. They should look like Javadocs. There
should be no general clauses which describe what exceptions can be
thrown from anything or some collections of functions. (Java has such
a thing, but C++ does not because C++ does not have asynchronous
exceptions.) Each function should have a throws description which
describes succinctly but fully what it can throw. Examples:
- nothrow (Ex: most C library functions)
- can throw bad_alloc
- throws any exception thrown from called user supplied code
- throws any exception thrown from the user supplied constructor or
copy constructor, and can throw bad_alloc (ex: lots of vector
functions)

Javadocs-like style really is the way to go. It's not that much extra
text to have "nothrow", "can throw bad_alloc on memory allocation
failure", etc., on each individual function specification, it would
really help implementers get it right, and it would help users
understand the actual guarantees implementers are supposed to
implement.

> Which for me means "you can't write portable C++
> program that uses STL". :-(

Now here I think you exaggerate. It's just that we're writing to
reference documents, facts of known implementations, and QoI, instead
of writing to an actual standard. It's still quite possible to write
programs using the STL which are portable in fact and practice, if not
by standard.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]