check boost::variant<T> for null
Asked Answered
P

5

19

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?

Priapitis answered 15/3, 2011 at 13:15 Comment(2)
Please forgive me if I misunderstand the question, however, according to Never Empty Guarantee, boost::variant seems not to get empty...Summer
None of the existing answers are good enough? what is missing?Diaphanous
H
18

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;
}
Heptane answered 15/3, 2011 at 13:32 Comment(1)
Addendum: this is, obviously, unlike boost::optional.Heptane
D
41

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

Diaphanous answered 5/10, 2011 at 22:32 Comment(1)
Oh nice, I did not know about boost::blank.Heptane
H
18

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;
}
Heptane answered 15/3, 2011 at 13:32 Comment(1)
Addendum: this is, obviously, unlike boost::optional.Heptane
R
4

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);
};
Rivas answered 15/3, 2011 at 14:7 Comment(0)
O
3

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.

Oleta answered 15/3, 2011 at 13:32 Comment(2)
Unless I'm misunderstanding something, I just want to check if the type inside the boost variant contains an actual value, cause doing a get<T> on it with no value, throws an exception, which I do not want...Priapitis
@Tony: what kind of exception? And have you considered the which member? boost.org/doc/libs/1_46_0/doc/html/boost/…Oleta
A
0

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.)

Arly answered 29/5, 2016 at 16:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.