Перебор Boost fusion::vector

Я пытаюсь перебрать вектор boost::fusion, используя:

typedef typename fusion::result_of::begin<T>::type t_iter;
  std::cout << distance(begin(t), end(t)) << std::endl;
  for(t_iter it = begin(t); it != end(t); next(it)){
    std::cout<<deref(it)<<std::endl;
  }

Оператор расстояния cout дает мне конечную длину (2), однако цикл, похоже, работает бесконечно.

Любые советы очень ценятся!


person arlogb    schedule 26.10.2012    source источник


Ответы (4)


Вы не можете просто повторять вектор Fusion таким образом, тип для каждого итератора может отличаться от предыдущего (и обычно так и есть). Я думаю, именно поэтому у вас нет it = next(it) в вашем коде, это приведет к ошибке компиляции.

Для этого вы можете использовать boost::fusion::for_each вместе с функциональным объектом, который выводит каждый элемент на стандартный вывод:

struct print
{
    template< typename T >
    void operator()( T& v ) const
    {
        std::cout << v;
    }
};

...

boost::fusion::for_each( t, print() );
person K-ballo    schedule 26.10.2012
comment
Спасибо! На самом деле я хочу присвоить каждому элементу вектора значение. Я предполагаю, что я должен сделать что-то подобное? - person arlogb; 27.10.2012
comment
@arlogb: Хотя вы могли бы сделать что-то подобное, вероятно, проще просто создать новую совместимую последовательность с новыми значениями и назначить ее целевой последовательности. - person K-ballo; 27.10.2012
comment
Спасибо за совет. К сожалению, я не знаю, сколько значений я хочу присвоить до времени выполнения, поэтому, хотя я бы использовал что-то вроде push_back на std::vector<T> здесь, я все еще немного не понимаю, как присваивать значения. - person arlogb; 27.10.2012
comment
@arlogb: Fusion Sequences — типизированные звери, у вас не может быть динамической последовательности. То есть результат push_back в последовательности приводит к созданию новой последовательности. - person K-ballo; 27.10.2012
comment
Хорошо, может быть, я не очень хорошо сформулировал свою проблему. По сути, я ожидаю, что что-то вроде fusion::vector<int, int, int> или fusion::vector<int, double> будет передано (шаблонной) функции, и хотел бы заполнить все, что я получаю, некоторыми значениями. - person arlogb; 27.10.2012

fusion — замечательная библиотека, и теперь вы должны понимать, что она во многом отличается от того, что вы используете в повседневных программах на C++. Она объединяет мощь метапрограммирования времени компиляции со средой выполнения. который может обрабатывать все элементы в контейнере fusion. Что это значит? это означает, что result_of::begin<T>::type не всегда совпадает с next(it), поэтому вы не можете использовать итераторы fusion в таком for.

Очевидная проблема в вашем коде заключается в том, что вы игнорируете возвращаемое значение next, и это приведет к тому, что ваш код будет работать вечно, но вы не можете использовать его в it = next(it), поскольку их тип может различаться!!

Так что же делать?? Вы должны использовать boost::fusion::for_each для этой цели

person BigBoss    schedule 26.10.2012

next на самом деле не продвигает итератор, он просто возвращает следующий.

Это можно увидеть в документах, поскольку функция next принимает постоянный аргумент, что означает, что она не может фактически изменить итератор:

template<
    typename I
    >
typename result_of::next<I>::type next(I const& i);
                                         ^^^^^
person chris    schedule 26.10.2012
comment
Ах да, вы совершенно правы. Есть ли способ продвинуть итератор тогда? Я вижу, что метод advance также принимает const, поэтому я предполагаю, что он также не перемещает итератор. - person arlogb; 27.10.2012
comment
@arlogb, продвижение того же итератора дает вам проблему, обсуждаемую в ответе К-Балло. Я бы предложил, чтобы общее повышение решения предусматривало повторение всего вектора, который равен for_each, что хорошо продемонстрировано для вас в том же ответе. - person chris; 27.10.2012

Проблема в том, что внутри цикла вы разыменование вашего итератора. Когда вы применяете к нему next, это ничего не значит, и поэтому ваш цикл работает вечно.

person alestanis    schedule 26.10.2012
comment
Я имел в виду, что @JesseGood разыменовывает ваш итератор. Спасибо! - person alestanis; 27.10.2012
comment
@arlogb на самом деле ответ (неправильное использование next) был дан К-балло и Крисом - person alestanis; 27.10.2012