в общем случае конвертировать из Boost :: Вариант <T>в тип - PullRequest
6 голосов
/ 06 декабря 2010

У меня есть 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);
                    }

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

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

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

Ответы [ 3 ]

11 голосов
/ 06 декабря 2010

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

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 имеет перегрузки для всех типов, вышеприведенное должно работать ...

2 голосов
/ 06 декабря 2010

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

Удачи!

0 голосов
/ 06 декабря 2010

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

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

...