Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is std::optional never "valueless by exception"?

std::variant can enter a state called "valueless by exception".

As I understand, the common cause of this is if a move assignment throws an exception. The variant's old value isn't guaranteed to be present anymore, and neither is the intended new value.

std::optional, however, doesn't have such a state. cppreference makes the bold claim:

If an exception is thrown, the initialization state of *this ... is unchanged, i.e. if the object contained a value, it still contains a value, and the other way round.

How is std::optional able to avoid becoming "valueless by exception", while std::variant is not?

like image 924
Drew Dormann Avatar asked Aug 28 '19 15:08

Drew Dormann


1 Answers

optional<T> has one of two states:

  • a T
  • empty

A variant can only enter the valueless state when transitioning from one state to another if transitioning will throw - because you need to somehow recover the original object and the various strategies for doing so require either extra storage1, heap allocation2, or an empty state3.

But for optional, transitioning from T to empty is just a destruction. So that only throws if T's destructor throws, and really who cares at that point. And transitioning from empty to T is not an issue - if that throws, it's easy to recover the original object: the empty state is empty.

The challenging case is: emplace() when we already had a T. We necessarily need to have destroyed the original object, so what do we do if the emplace construction throws? With optional, we have a known, convenient empty state to fallback to - so the design is just to do that.

variant's problems from not having that easy state to recover to.


1 As boost::variant2 does.
2 As boost::variant does.
3 I'm not sure of a variant implementation that does this, but there was a design suggestion that variant<monostate, A, B> could transition into the monostate state if it held an A and the transition to B threw.

like image 70
Barry Avatar answered Sep 21 '22 16:09

Barry