
in a = b; , we can have exception-safe assignment if we have, or can simulate, nothrow move of either a's current type (move a to backup on stack first, then try copying b; if it fails, move a back from the stack, if it succeeds, destruct a-on-stack) or b's current type (copy b to stack first, and if that succeeds, destruct a and move the copy of b that's on the stack to a). The current implementation of variant tries to detect whether that nothrow move exists for a. It does for builtin types. If it does, then it uses a completely safe implementation. If it doesn't, it uses an implementation that still has a useful property: 1. If the type has nothrow copy-construction, we are completely safe, whether or not Boost.Variant can detect it. 2. It doesn't need nothrow copy-construction *in general*, it only needs to be able to copy-construct again something that was copy-constructed the first time, in particular something like: type a_copied(a); //may throw a.~type(); //it's in variant, so must be nothrow new (&a) type(a_copied) //we wish this to never throw Of course, 3. guaranteeing that with "interesting" types is prone to race conditions 4. many types, such as std::vector, use dynamic memory allocation, which in theory (and maybe in some real situations) may throw. However, things may not be as bad as they look. If a type has nothrow swap and a nothrow constructor (e.g. default-constructor) then we can simulate nothrow swap. However std::vector appears to have no nothrow constructors. So we're actually stuck even if just two of the types in the container are standard-container types. (although, arguably the default-constructor+swap is less likely to throw, so it could be attempted if it seems worth the complexity/impossibility of detecting default-constructibility, possibly as a fallback after copy-construction has thrown or vice versa) We can also simulate "move" by copying bits around, but that solution was rejected. After all, they would have to be bits representing a's type or b's type, and we don't have a lot of guarantees about that type. Types for which it's absolutely definitely safe to copy bits around, have nothrow copy-construction anyway. Any further hacks in this area really need to go in a Boost.Move library. Also, if we're willing to put up with possible variant contents on the heap when the type's copy-constructor threw, and in the hopeful policy-based future when we can actually say we want Variant's heap-behavior rather than the nothrow-default-construction behavior, we can get the type-preserving strong-exception-guarantee invariant, without any C++0x features. Looking to the future, why doesn't the draft C++0x standard's type-traits include: has_nothrow_move_constructor has_nothrow_move_assign has_nothrow_destructor ? With has_nothrow_move_constructor, we could implement the strong exception guarantee for assignment for all Variants that had at most one type that lacked a nothrow move-constructor. Without it, we can't be quite as smart, and could only guarantee strong exception safety for assignment when *all* the variant's types have nothrow move-construction. But if all the variant's types have nothrow move, then the variant itself has nothrow move. Did anyone come up with a type that legitimately has a move-constructor that can throw (even when the destructor can't throw, per Variant's existing requirements)? -Isaac