check boost::variant<T> for null

好久不见. 提交于 2019-12-02 22:36:15

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;
}
lurscher

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!