I already know how to use std::variant
fairly well with std::get_if()
, std::get()
and std::visit()
. But, what if I just want a simple way to tell if a variant has ever been initialized to any value? That is, I don't care what the value is, I just want a boolean test. How do I do that?
For example, suppose I declare a variant on the stack:
std::variant<int, double> data;
Then, my function goes on and might or might not initialize this variable. At the end of my function, I want to test if it was initialized.
index()
function. That returns 0 both for an uninitialized variant and for one I initialize to the first type declared.valueless_by_exception()
function but that returns false whether I initialize the variant or not.About the only thing I could think of to compare it to a default constructed one, like this:
using Data = std::variant<int, double>;
Data data;
// ... code here that might initialize data or might not...
if (data == Data())
// Not initialized
else
// Initialized
This seems to work, but reading the comments on operator==()
for std::variant
, it seems like this behavior is undefined.
So, is this a safe way to test, or is there another way?
std::variant<int, double> data;
data
is initialized. A std::variant
is always initialized with one of its values, unless it's valueless_by_exception()
.
Unless a std::variant
instance has an explicit constructor, the first variant alternative gets default-constructed. This specific data
holds an int
value, that's default-constructed.
If the first std::variant
value does not have a default constructor than the variant cannot be default-constructed, and must have an explicit constructor.
When it is desired to have a concept of a variant that doesn't "really" (with the word "really" in air-quotes) have a default value: the usual convention is to have std::monostate
as the first variant value. This is what std::monostate
is for.
std::variant<std::monostate, int, double> data;
This variant is default-constructed and holds a std::monostate
value. Its index()
is 0. You can consider this variant to be uninitialized, whatever that actually means to your application, when your variant has a 0 index.
There's nothing special about std::monostate
itself. It's just an empty class. If you visit a variant with a std::monostate
value your visitor needs to deal with a std::monostate
alternative.