2017-05-28 12:59 GMT+02:00 Niall Douglas via Boost
I'll ask the same I asked Peter, because I no longer see the value in never-empty guarantee.
If I have two objecte of type variant, where A, B can throw on copy/move, and C is trivial:
``` variant a = A{}, b = B{};
try { a = b; // throws } catch(...) {}
// at this point a holds a C ```
What good does it make to me that I had an A, wanted to assign a B and got a C?
Why would you get a C in 'a'?
'a' previously was set to A.
The assignment of 'b' with B state to 'a' failed due to exception.
I am describing `boost::variant` which tries to provide both "never-empty" guarantee and "no double storage" guarantee. But it does not provide the strong guarantee: In short, if you assign to a, first the A is destroyed, second, we attempt to copy-construct a B. It fails: we have no A (already destroyed) and no B (construction failed), so it will default-construct a C, because this is guaranteed not to throw. So the never-empty guarantee is preserved, but you get some other value, you have no use for. This is documented here: http://www.boost.org/doc/libs/1_64_0/doc/html/variant/design.html#variant.de...
So the strong never empty guarantee implemented by both Outcome and Expected means that 'a' still contains its original A untouched and undamaged. 'b' also contains its B untouched and undamaged, though that is up to B's copy constructor.
I wonder if this is possible. In `result` you have a T an an error_code_extended. If you are assigning to an errored result: ``` outcome<T> o = make_errored_result(xxx); outcome<T> v = T{yyy}; o = v; ``` What do you do? First you need to destroy the error_code_extended stored by `o`. Then you try to copy-construct T in the same storage. If it fails, you have no error to return to: you have just destroyed it, and possibly overwrote the storage. So I fail to see how you can implement a strong guarantee for the assignment, unless you apply no-throw restrictions on type T. Regards, &rzej;