I have a boost::variant in my program and I want to check if the variant itself is initialized and also if there is a value contained in one of it's types.
I've tried empty() on the variant, but that doesn't seem to work. Neither does checking against NULL.
Does anybody know how to check for this?
EDIT: Ok, It seems it will never be empty, but there will not always be a value in it's contained types, so how do I check for a no-value situation?
A boost::variant
is always initialized.
If you did not initalized it explicitly, the first item was constructed using its default constructor:
struct Foo {};
struct Bar {};
struct Visitor: boost::static_visitor<>
{
void operator()(Foo const& foo) const { std::cout << "Foo\n"; }
void operator()(Bar const& bar) const { std::cout << "Bar\n"; }
};
int main(int argc, char* argv[])
{
boost::variant<Foo,Bar> var;
boost::apply_visitor(Visitor(), var); // prints Foo
return 0;
}
if you see my question regarding never empty guarantee and single storage, boost::variant
does support a NIL-like value type called boost::blank
. which will guarantee that variant never uses the heap as backup storage
You can detect which type is stored using boost::variant<>::which()
which returns an integer index of the binded variant type; so if you use blank as the first type, which() will return 0 when its blank
see the following example
typedef boost::variant< boost::blank , int , std::string > var_t;
var_t a;
assert( a.which() == 0 );
a = 18;
assert( a.which() == 1 );
hope this helps
One method for making sure that you have a well defined variant is to include a "NullType" in your variant list. While it may neccessitate writing more code in the "visitors" you will write to use it, they can throw exceptions to let operators know something is amiss. I'm generally against such runtime checks but sometimes, there really isn't any other way. Suffice to say that:
class NullType{};
Then add it as the very first argument to the variant list. As others have said and the boost documentation describes you'll never have a situation where a variant is empty. However, you can do a type check to ensure that you won't ever be able to compile with "NullType" if you don't overload functions or have a runtime exception thrown if you do have a "NullType".
Now your variant:
boost::variant<NullType, int, double, long double> number;
class DoSomething : boost:static_visitor<void>{
public:
void visit(const int& _item);
void visit(const double& _item);
void visit(const long double& _item);
void visit(const NullType& _uhOh);
};
Boost.Variant has a never-empty guarantee, which means it must always store some value. It's empty
member is guaranteed to always return false
and exists only for compatibility.
You may want to check out Boost.Any instead.
You also can use
boost::variant<boost::blank, int, double, long double> number;
And variant function empty()
. It returns false if variant always contains exactly one of its bounded types. (See the section called Never-Empty Guarantee for more information.)