
On 21.01.2013 17:39, Antony Polukhin wrote:
I: Leave it as is - bad performance - can not provide noexcept guarantee
I vote against this solution because of it's disadvantages.
II: Set operand.p_ to NULL, add BOOST_ASSERT in get operations + good performance + provides noexcept guarantee for move constructor + optimization will be used even if varinat has no type with trivial default constructor + easy to implement - triggers an assert when user tries to reuse moved object - adds an empty state to the recursive_wrapper Let's think about non-recursive variants. For example:
// both CFileObj and CDatabaseObj are movable, not copyable and // not nothrow-default-constructible boost::variant< CFileObj, CDatabaseObj > v1( CFileObj(SomeFileName) ); boost::variant< CFileObj, CDatabaseObj > v2( std::move( v1 ) ); // What would be the state of v1 at this point? It seems to me that the second solution solves only a part of the problem. So, I don't vote for it.
III: Make recursive_wrapper and variant cooperate, enable move for varinat in the presence of recursive_wrappers only when there is at least one type that is nothrow-default-constructible, regardless of whether it's current. It is easyer to understand by example: typedef variant<int, recursive_wrapper<foo>> V; V v1( std::move(v2) ); This move-constructs v1 from v2 and leaves int() into v2. + good performance + provides noexcept guarantee for rcursive_wrapper + does not adds an empty state - optimization won't trigger if varinat has no type with trivial default constructor - hard to implement - user may be obscured by the fact, that v2 from the example now contains int
I think this is a best solution. We have to leave the moved-from object in some valid state and cannot specify this state in the code. So, we need the default constructor (or, may be, something else).
IV: After move away, delay construction of type held by recursive_wrapper till it will be be required. +/- good performance? but more checks + provides noexcept guarantee for rcursive_wrapper + does not adds an explicit empty state + optimization will be used even if varinat has no type with trivial default constructor +/- not hard to implement --- additional requirement for type T of recursive_wrapper: it must be default constructible - less obvious behavior for user (for example get() function would construct values, allocate memory and can possibly throw) I think that get() MUST NOT throw. So, I vote against this solution.
-- Sergey Cheban