Увеличить значение boost::variant

У меня есть вариантная переменная, в которой все разные типы реализуют operator++. Я хотел бы применить приращение непосредственно к переменной варианта. Есть ли простой способ сделать это? Или я должен применить его в переключателе для каждого типа?

Простой пример с итераторами stl:

typedef boost::variant<
  std::vector<double>::iterator,
  std::vector<double>::reverse_iterator,
  std::set<double>::iterator,
  std::set<double>::reverse_iterator
> AnyIterator;

void incr(AnyIterator& ai)
{
  ++adi; // this doesn't compile: no match for operator++ blah blah blah

  // Have I really to write this kind of ugly thing ?
  if(ai.type() == typeid(std::vector<double>::iterator))
    ++boost::get<std::vector<double>::iterator>(ai);
  else if(ai.type() == typeid(std::vector<double>::reverse_iterator))
    ++boost::get<std::vector<double>::reverse_iterator>(ai);
  else if(ai.type() == typeid(std::set<double>::iterator))
    ++boost::get<std::set<double>::iterator>(ai);
  else if(ai.type() == typeid(std::set<double>::reverse_iterator))
    ++boost::get<std::set<double>::reverse_iterator>(ai);
}

Примечание. Я использую gcc 4.8.1 и Boost 1.57. Мне не нужно решение от C++11, я не могу его использовать из-за совместимости со старыми версиями gcc.


person Caduchon    schedule 30.05.2016    source источник
comment
Я не думаю, что вы можете избежать написания этого уродливого кода, но если он вам часто нужен, вы можете реализовать оператор ++ для своего типа AnyIterator.   -  person Holt    schedule 30.05.2016


Ответы (1)


Вы можете определить общий функтор, а затем использовать boost::apply_visitor с этим функтором:

namespace detail {
struct incrementer {
    template< typename T >
    void operator()(T& x) const { ++x; }
    typedef void result_type;
};
}

void incr(AnyIterator& ai)
{
  boost::apply_visitor(detail::incrementer(),ai);
}
person cpplearner    schedule 30.05.2016
comment
Я вижу идею. Это выглядит просто. Можете ли вы попробовать скомпилировать свое решение? У меня есть ошибка компиляции о выводе шаблона с несколькими предложениями в примечаниях (слишком длинные для комментария). Более того, зачем помещать структуру в пространство имен detail? Это просто нехорошая практика? По какой причине? - person Caduchon; 30.05.2016
comment
@Caduchon Я не вижу ошибки. пространство имен detail действительно не нужно. - person cpplearner; 30.05.2016
comment
Ебаный Бог! Я пропустил typedef void return_type;. Ошибку действительно невозможно понять! Спасибо, теперь работает. - person Caduchon; 30.05.2016
comment
Кажется, лучший способ - это наследование от boost::static_visitor<>. Но идея есть. - person Caduchon; 31.05.2016