Variant is a replacement for raw
union use. It is type-safe and knows what type it is, and it carefully constructs and destroys the objects within it when it should.
It is almost never empty: only in corner cases where replacing its content throws and it cannot back out safely does it end up being in an empty state.
It behaves somewhat like a
std::tuple, and somewhat like an
std::get_if is usually a bad idea. The right answer is usually
std::visit, which lets you deal with every possibility right there.
if constexpr can be used within the
visit if you need to branch your behavior, rather than doing a sequence of runtime checks that duplicate what
visit will do more efficiently.