Как получить текущий вариантный тип и определить новые переменные этого типа
У меня есть импульс:: вариант таких типов, как:
typedef boost::variant< uint8_t, int8_t, uint16_t, int16_t,
uint32_t, int32_t, float, double, std::string > StorageTt;
StorageTt
переменная, скажем val
, установлен в один из этих типов хранения позже в моем коде. Я хотел бы получить тип, который val
в настоящее время имеет право определить больше переменных того же типа. Так что если val
в настоящее время uint16_t
Я хочу сделать что-то вроде:
typedef decltype(typeid(val)) StorageTt;
StorageTt new_val = 32.0; // new_val should be a uint16_t
но это дает константный тип type_info. Я знаю, что могу сделать:
switch (val.which()) {
case 0: // uint8_t
case 1: //...
но я бы предпочел избежать длинного описания случая, потому что я должен сделать это несколько раз.
3 ответа
Вы можете сделать что-то подобное, используя функтор посетителей с шаблоном оператора вызова:
struct MyVisitor : public boost::static_visitor<>
{
template <typename StorageT>
void operator()(const StorageT&) const
{
StorageT new_val = 32; // declare variable with same type
doSomethingWith(new_val); // do something with it
}
};
Примените это к варианту val
вот так:
boost::apply_visitor(MyVisitor(), val);
Ссылка:
boost::variant
Основное использованиеboost::apply_visitor
boost::static_visitor
Я не знаю, как заменить функтор на лямбду C++14.
Тебе этого не сделать. Переменные являются синтаксическими конструкциями. Это имена для программных объектов. Имена существуют только в исходном коде.
Рабочий процесс выглядит следующим образом. Сначала вы пишете источник. Затем вы компилируете его, запускаете программу, и она выполняет некоторые действия, например, получает значение из boost::variant
объект. На данный момент вы не можете определить какие-либо имена. Нет источника, нет имен, нет синтаксиса. Есть только объекты.
Если вам нужен новый объект того же типа, что и полученный из варианта, тогда StorageT new_val(val);
создает только это (новый объект скрыт в new_val
, вы получаете доступ к нему с boost::get
или же boost::apply_visitor
или что угодно).
Если вы хотите выполнить действие для любого варианта, который у вас есть, и все действия выглядят одинаково, и отличаются только их типы (они не одинаковы, потому что типы разные, они просто выглядят одинаково), и вы хотите не пишите одни и те же вещи несколько раз, тогда, конечно, шаблоны - ваши друзья. boost::apply_visitor
с template<typename> operator()
является правильным:
struct my_assignment_visitor: public boost::static_visitor<>
{
template <typename T> void operator()(T & var, double val) const
{
var = val;
}
};
boost::apply_visitor(my_assignment_visitor(), new_val, 32.0);
Использование конструктора копирования должно работать:
// construct object of same type as val
StorageT new_val(val);
boost::get(new_val) = 32.0;