Andrzej Krzemienski wrote:
So, does the following recommendation correctly capture the design goals for boost::variant2?
If you require the never-empty guarantee (and accept the costs) use boost::variant2.
If you do not require the never empty guarantee use std::variant.
Kind of, but as written this implies that std::variant has no costs, which is not true. The checks for valueless do carry a cost. Each visit(), for example, starts with `if(valueless) throw`, which is not necessary in variant2.
Also, I am not entirely satisfied with the reply, "those who want this guarantee". Could you, or anyone else, give me a real-world use case where a never-empty guarantee is needed, but a strong exception guarantee is not?
My reply was unsatisfactory because I was really not looking forward to
rehashing the arguments against singular states. Singular state is bad when
a result of two-phase construction (which is why we no longer use two-phase
construction), it's bad when a result of exception (which is why we don't
use destroy-only exception safety but basic exception safety), it's bad when
a result of default initialization of built-in types (but we can do nothing
about it), and it's bad when a result of a move (which is why move
semantics, as originally specified, do not put the moved-from object in a
singular state.)
Singular states introduce implicit "is_valid" preconditions on all your
normal functions, and partition the program into two worlds, a normal world
where no object is singular, and an "exceptional" world where objects may be
singular. It's _possible_ to program in this way, but it's not fun, because
world #2 may never call into world #1 under penalty of undefined behavior,
and singular objects are never to enter world #1, because this sets up a
delayed explosion.
If you avoid singular states, this removes all these implicit "is_valid"
preconditions, which removes the partitioning and collapses the two worlds
back into one; "type 2" code can call "type 1" code and nothing undefined
will happen.
Now in principle, for the specific case of move, it's possible and sound to
specify it to leave the object in a singular state, provided that you only
ever move from objects that are about to be immediately destroyed. But
that's not the approach that was taken. In this timeline, move does not
leave objects in a singular state, so there is no requirement to only ever
use it on objects that are about to be destroyed.
For variant specifically, the guarantee that variant