2013-04-03 2 views
1

Должен ли я использовать класс посетителя, такой как class Visitor : public boost::static_visitor<> с boost :: variant?Является ли требование класса гостей: вариантом варианта?

Если нет, есть ли причины не использовать посетителя? Есть ли причины, чтобы предпочесть класс посетителей?

Я задаю этот вопрос, потому что класс посетителей выглядит излишним аспектом использования boost :: variant.

ответ

5

Вы не обязаны использовать посетителя, вы можете идеально запросить базовый тип, используя get<T>().

Это приводит к такому коду:

int foo(boost::variant<int, std::string, Bar> const& v) { 
    if (int const* i = get<int>(&v)) { 
     return *i; 
    } 
    if (std::string const* s = get<std::string>(&v)) { 
     return boost::lexical_cast<int>(*s); 
    } 
    if (Bar const* b = get<Bar>(&v)) { 
     return b->toInt(); 
    } 

    std::abort(); // ? 
} 

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

С другой стороны, следует ли использовать вариант, если вы когда-либо не обрабатываете случай (тип), вы будете уведомлены об ошибке времени компиляции.

В моих глазах использование boost::static_visitor бесконечно превосходит ... хотя я использовал альтернативу get<T>() пару раз; обычно, когда мне нужно только проверить один (или два) типа и не волнует (вообще) всех остальных. Альтернативой будет использование посетителя с перегрузкой template <typename T> void operator()(T const&) const;, что не обязательно является чище.

+0

Могу ли я не просто запрос для базового типа с помощью 'SomeVariantVariable.which()', который будет возвращать индекс варианта 'ЬурейеЕ повышения :: variant_variable' декларацию и указать, какой тип: Type1 = 0, Type2 = 1? – Mushy

+0

@Mushy: вы можете «да», а затем «переключитесь» на это и вызовите 'get()'; но на данный момент вы просто переопределяете код, вызывающий посетителя ... за исключением того, что если кто-то добавляет тип в середине списка, тогда индексы сдвигаются, и, таким образом, 'get()' может возвращать значение null, которое вы должны учитывать для (или аварии). –

0

Если вы хотите иметь какую-либо операцию по варианту, например некоторую проверку, вы можете захотеть получить ее в качестве посетителя.

struct to_str : boost::static_visitor<std::string> 
{ 
    template<class T> 
    std::string operator()(T const & x) const 
    { 
     return boost::lexical_cast<std::string>(x); 
    } 
}; 

С другой стороны, если вы хотите, например, проверить, если он int и сделать что-то с ним, вы, вероятно, использовать boost::get например

if(const int * my_int = boost::get<int>(&my_var)) //no-throw form 
{ 
    //do smth with int 
} 
Смежные вопросы