в общем случае преобразовать из boost:: variant в type

у меня есть typedef boost::variant<int, float, double, long, bool, std::string, boost::posix_time::ptime> variant который я использую для хранения различных типов значений в структуре. Только один из определенного типа когда-либо будет храниться в этой структуре, однако у меня есть вектор этих структур, которые мне нужно пройти и получить фактический тип из варианта.

Теперь, когда мне нужно сделать преобразование типов из этого варианта, я делаю это:

variant second = mystruct.variant;
                                if (second.which() == 5) //string 
                    {
                        std::string val = boost::get<std::string>(second);
                        modvalue->AddNodeAttribute(key, val);
                    }
                    else if (second.which() == 0) //int
                    {
                        int val = boost::get<int>(second);
                        modvalue->AddNodeAttribute(key, val);
                    }
                    else if (second.which() == 2) //double
                    {
                        double val = boost::get<double>(second);
                        modvalue->AddNodeAttribute(key,val);
                    }
                    else if (second.which() == 1) //float
                    {
                        float val = boost::get<float>(second);
                        modvalue->AddNodeAttribute(key, val);
                    }
                    else if (second.which() == 3) // long
                    {
                        long val = boost::get<long>(second);
                        modvalue->AddNodeAttribute(key, val);
                    }
                    else if (second.which() == 4) // bool
                    {
                        bool val = boost::get<bool>(second);
                        modvalue->AddNodeAttribute(key, val);
                    }
                    else if (second.which() == 6) // posix::time
                    {
                        boost::posix_time::ptime ptm = boost::get<boost::posix_time::ptime>(second);
                        modvalue->AddNodeAttribute(key, ptm);
                    }

Я задавался вопросом, есть ли более общий способ обойти это, написав общую функцию это принимает вариант и тип T, который является возвращаемым значением. Но когда я это делаю, мне все равно нужно написать подобную кучу операторов if для учета каждого типа T.

что-то вроде FromVariant<int>(var);, но тогда мне все равно придется делать это для каждого типа в моем варианте.

поэтому кажется, что мое общее решение не уменьшает мой код, а увеличивает его, что, очевидно, не имеет значения. Я задавался вопросом, есть ли у кого-нибудь более элегантное решение для получения различных типов из моего вариант, который является несколько общим, где я могу просто вызвать функцию, дающую тип, который я хочу вернуть?

3 ответов


на самом деле, глядя на ваш код еще немного, вот другой вариант - снова на основе использования посетителя..

struct add_node_visitor : boost::static_visitor<>
{
  add_node_visitor(<type of modvalue> & node, <type of key> & key) : _node(node), _key(key) {}

  template <typename _Item>
  void operator()(_Item const& item)
  {
    node->AddNodeAttribute(_key, item);
  }  

  <type of modvalue> & _node;
  <type of key> & _key;
}

использование:

boost::apply_visitor (add_node_visitor(modmodvalue, key), mystruct.variant);

пока ваша AddNodeAttribute имеет перегрузки для всех типов, выше должно работать...


когда я использовал boost::variant Я всегда буду получать доступ к содержащимся данным, используя технику посетителя. На мой взгляд это очень элегантный способ. Он не полагается на логику переключения, что на самом деле является признаком плохого дизайна. Вижу документация.

удачи!


... Что делает AddNodeAttribute? По сути, одно и то же для каждого типа, верно? Если у вас где-то есть контейнер атрибутов узла, то он в основном должен быть контейнером типа variant, верно?

... Так почему бы просто не переписать AddNodeAttribute как единственную функцию, принимающую вариант?