On Wed, 6 Nov 2002 16:21:34 -0300, "Fernando Cacciola" <[EMAIL PROTECTED]> wrote:
>OK, my fault. >I wasn't thinking of directly using StrongStorage<T>... >I was thinking of borrowing its idea, so I meant that using some variation >of the double-buffer technique, you could achieve no-throw. Though I should >have said so explicitely, sorry. Yeah, I understood that (I'm not so 'inelastic'! :-). However your insistence on no-throw made me go to the original code to show that not even there there's a no-throw guarantee. Of course, I agree with you that the technique allows us to have the strong guarantee. >> >> Now, as I said, I DO NOT have the code of construct_as () because I >> haven't found it in any place, but if it uses copy construction (as I >> suppose) and if the copy may throw then that swap cannot provide the >> nothrow guarantee. We agree on that, I think. Now let us see other >> points: >> >You are right here, construct_as(), which is in "aligned_storage.hpp" in the >sandbox, uses the copy ctor, so StrongStorage<T>::swap is not designed as >no-throw. Ok. [...] >> > restore_previous_state_without_throwing(); >> >> Same note, of course. >> >OK. Since I've actually cheated by showing what should be done instead of >how to do it, I've noticed that this couldn't possible work AFAICT. This >restore, unlike the save, not only should not throw but also succeed: i.e: >copy back all elements without failure. Exactly. That's why I asked how did you do that. I agree however that the show-stopper is the restore not the save part. > >> > throw; >> > } >> >} >> > >> >A no-throw swap would be essentially the same except that exception >possibly thrown by the T's swap are eaten. >> > >> >Do we agree that the above is the minimun 'traditional' implementation? >> >> It depends. Don't make me say that :-) Once you are in the catch and >> you have swapped N/2 objects... >> >Before we get into the details of the double buffer, let me try to put my >thoughts into perspective. >We have an Array class which has two internal arrays: one dynamically >allocated and another automatically allocated. >If I am understanding the design correctly, at any time, only one of these >internal arrays represents the state of the Array. >If it is the dynamic array, then swap is not a problem since we just swaps >pointers. That's easy. >But what if the automatic array is the one currently active? >How would you implement swap() and which exceptions guarantees would you >achieve? >-- please answer here -- Well, I agreed with you since the beginning that the technique is useful for the strong guarantee. I hope that's clear now. My objection concerned "no throw". >Now, without the double buffer, my only answer to the question above *would* >be the 'traditional' implementation I've shown. However, even that doesn't >work because the restore cannot be made to succeed, AFAICT, in the presence >of throwing copy ctor. > >So, since *I* do not have a clue about how to implement a swap with at least >strong guarantees without the double buffer, I propose it. >However, you or someone else might know how to do the same without this >complicated scheme (and without relying on the presence of a no-throw T's >swap). In that case, though, I will love to hear about it. I don't know either. However I'm still not convinced that a strongly exception-safe swap is really useful for an array-like class like that. I'm not saying it isn't, only that I'm not convinced it is. Do you have any example that can make me change my mind? >> > if ( storage_initialized_[mirror_idx] ) >> > lhs_mirror->~T(); >> >> Who says you that you can invoke the destructor on all the N elements? > >This code is destructing the element which has been previously stored in the >'mirror' storage. I think you missed my point. You don't know how many Ts have been successfully constructed in the storage. Let's say N=8 and the 3rd copy constructor fails: you must destroy only the first 2 elements. But that was a minor note that I had better left aside considering the extemporaneousness of the code. Furthermore that's trivial to fix by preserving the value of i and looping backward. Ok so far. Now that we have understood each other it's time for another problem :-) Can you think of a situation where a swap between arrays with different values of N is useful? That adds special cases to the code, of course: suppose e.g. you want to swap an array<T, 10> that happens to have 12 elements and an array<T, 15> that has 5 elements. It's easy but you have to stuff the code with several ifs. And that's one of the aspects I was thinking to when saying that a) I'm not sure there's a remarkable gain in performance (of course there can be for some values of N but... maybe on your platform only, maybe for some scenarios only... a complex story IMHO) and b) if a gain exists, if it is worth the complexity. Also note that, in the end, the user can only count on the strong guarantee for swap. One wants to know in compile-time what are the guarantees, of course. Our array<T, N>::swap() instead offers different guarantees depending on whether it has more than N elements or not. Obviously this means that, generally, the designer of the client code will rely on the weakest of the two. Genny. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost