Boost seems to have two implementations of a variant class template:
It is rare (though not unheard of) for Boost to include two takes on the same concept. Why has this happened for variants? How do these variants differ?
The first kind of variant class template, boost::variant
, predates C++17's std::variant
. See this question for its comparison to std::variant
. Mainly, the difference regards what to do when an exception is thrown on construction of a value within the variant.
The std::variant
choice is to allow a valueless state; the boost::variant
choice is to construct the new object on the heap, not in-place, and store a pointer to that location.
boost::variant2
is a later addition, which, on the one hand, wishes to adhere to the C++17 API, but on the other hand is an expression of dissatisfaction with its choice on this matter.
boost::variant2
chooses a third option, different than both previous implementations: double-buffering. It takes up twice the size of the problematic type; constructs a new value in the unused half, and once the construction succeeds - destroys the old value in the other half. If all types are nothrow-move-constructible, this is not necessary and boost::variant2
will not actually have the double buffer.
This choice means that boost::variant2
can never be valueless; and indeed, its documentation title emphasizes this fact.