Prev: Is there any standard/guarantees for exception safety in STL operations?
Next: Is there any standard/guarantees for exception safety in STL operations?
From: Bo Persson on 27 Jul 2010 06:48 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 27 Jul 2010 14:32 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 27 Jul 2010 14:33 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 27 Jul 2010 15:39
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! ] |