Check boost:: variant <T> для null

У меня есть boost:: variant в моей программе, и я хочу проверить, инициализирован ли этот вариант, а также если есть значение, содержащееся в одном из его типов.

Я попробовал empty() для варианта, но это не работает. Также не проверяет NULL.

Кто-нибудь знает, как это проверить?

EDIT: Хорошо. Кажется, он никогда не будет пустым, но в нем не всегда будут значения, содержащиеся в типах, поэтому как я могу проверить ситуацию без значения?

Ответы

Ответ 1

A boost::variant всегда инициализируется.

Если вы явно не инициализировали его, первый элемент был создан с использованием его конструктора по умолчанию:

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

Ответ 2

если вы видите мой вопрос о неиспользуемой гарантии и отдельном хранилище, boost::variant поддерживает тип значения типа NIL, называемый boost::blank. который гарантирует, что этот вариант никогда не использует кучу в качестве резервного хранилища

Вы можете определить, какой тип хранится с помощью boost::variant<>::which(), который возвращает целочисленный индекс типа привязанного варианта; поэтому, если вы используете пустой как первый тип, который() вернет 0, когда его пустой

см. следующий пример

 typedef boost::variant< boost::blank , int , std::string > var_t;
 var_t a;
 assert( a.which() == 0 );
 a = 18;
 assert( a.which() == 1 );

надеюсь, что это поможет

Ответ 3

Один из способов убедиться, что у вас есть хорошо определенный вариант, - включить в список вариантов "NullType" . Хотя может потребоваться написать больше кода в "посетителях", которые вы напишете, чтобы использовать его, они могут создавать исключения, чтобы операторы знали, что что-то не так. Я вообще против таких проверок времени выполнения, но иногда нет другого пути. Достаточно сказать, что:

class NullType{};

Затем добавьте его как самый первый аргумент в список вариантов. Как говорили другие, и в документации по ускорению вы никогда не столкнетесь с ситуацией, когда вариант пуст. Тем не менее, вы можете сделать проверку типа, чтобы убедиться, что вы никогда не сможете скомпилировать с помощью "NullType" , если вы не перегружаете функции или не создаете исключение времени выполнения, если у вас есть "NullType" .

Теперь ваш вариант:

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

Ответ 4

Boost.Variant имеет никогда непустую гарантию, а это значит, что он всегда должен хранить некоторое значение. Он empty член всегда будет возвращать false и существует только для совместимости.

Вместо этого вы можете проверить Boost.Any.

Ответ 5

Вы также можете использовать boost::variant<boost::blank, int, double, long double> number;

И вариантная функция empty(). Он возвращает false, если вариант всегда содержит ровно один из его ограниченных типов. (Дополнительную информацию см. В разделе Never-Empty Guarantee).