
On Mon, Aug 4, 2008 at 7:00 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Emil Dotchevski wrote:
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.
I have 3 variants of values, let's call them V0, V1 and V2. V0 values are of type std::string, and V1 and V2 values are of type float. However, boost::variant<std::string,float,float> is illegal;
Then you should use tags, and not ugly hacks.
Variant can be implemented in three (four?) different techniques (temporary heap backup, nothrow copy or move, nothrow default constructor). Only the last one (which is, unfortunately, the one invoked by your code), does not satisfy strong exception-safety. It's fairly funny how an optimization diminishes the safety of variant.
In my opinion the tradeoffs of basic exception guarantee in this case are bigger than usual: the behavior it brings is very similar to an object changing its type. These semantics are not compatible with the usual semantics of operator=. I understand that there are use cases where it is unreasonable to pay the price of strong exception guarantee, but those cases can be supported with a separate operation with a name that hints about the unusual, possibly type-changing semantics. Also, I am not necessarily advocating strong exception guarantee. I would be fine if the semantics of operator= were such that it may leave the object in a particular unusual state. The problem is that as it is now, it may leave the object in a seemingly OK state. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode