
Hi Emil, On Wed, Jul 30, 2008 at 6:36 PM, Emil Dotchevski <emil@revergestudios.com>wrote:
Reading boost::variant's documentation:
"If any bounded type is nothrow default-constructible (as indicated by boost::has_nothrow_constructor), the library guarantees variant will use only single storage and in-place construction for every bounded type in the variant. Note, however, that in the event of assignment failure, an unspecified nothrow default-constructible bounded type will be default-constructed in the left-hand side operand so as to preserve the never-empty guarantee."
Do I read correctly that in an attempt to assign one variant object to another, the left-hand object _might_ silently change its type?
If an exception is thrown during assignment to a boost::variant<T0, T1, ...>, and one of the Ti is nothrow default-constructible, then the boost::variant will end up with a default-constructed value of one of those Ti. So even if the type happens already to be that Ti, the value will still change to the default value. This makes it very difficult for the user to enforce some useful
invariants for types that have boost::variant members, which in my mind is very important.
I'd like to understand your situation better-- could you elaborate on the use case you are facing?
Wouldn't it be better to guarantee that operator= either succeeds or doesn't change the observable state of the left-hand side operand, even at the cost of memory allocation? In that case the other behavior may still be provided through a separate function.
That would be the strong guarantee of exception safety. Right now, boost::variant provides only the basic guarantee for assignment. As a rule, I think providing the strong guarantee should be done only when it can be implemented efficiently. But again, I'd be interested to know the sort of situation you're facing. Eric