В C++, как перебирать массив в обратном порядке, используя для каждого?

В C++11, используя lambda / for_each, как мы итерируем массив из конца?

я попробовал следующее, но оба результата в бесконечном цикле:

for_each (end(A), begin(A), [](int i) {
   ....
});

for_each (A.rend(), A.rbegin(), [](int i) {
    ...
});

есть идеи? Спасибо.

3 ответов


вы пропустили это ?

Flip ваш rbegin & rend

for_each (A.rbegin(), A.rend(), [](int i) {
    ...
});

увеличение обратного итератора перемещает их к началу контейнера


std::for_each( A.rbegin(), A.rend(), [](int i) { /*code*/ } ); это самое простое решение.

я написал backwards который принимает последовательность, извлекает begin и end итератор из него с помощью free begin и end функции (с std::begin и std::end using объявления рядом -- full ADL), создает вокруг них обратные итераторы, а затем возвращает последовательность с этими двумя обратными итераторами.

это вроде аккуратно, потому что вы получаете этот синтаксис:

for( int i : backwards(A) ) {
  // code
}

что я нахожу легче читать, чем std::for_each и руководства for петли.

но я немного чокнутый.

вот минимальный backwards. Полное решение обрабатывает adl и несколько угловых случаев лучше.

template<class It, class C>
struct range_for_t{
  It b,e;
  C c; // for lifetime
  It begin()const{return b;}
  It end()const{return e;}
}
template<class It, class C>
range_for_t<It,C> range_for(It b,It e,C&& c){
  return {std::move(b),std::move(e),std::forward<C>(c)};
}

template<class It>
range_for_t<It,int> range_for(It b,It e){
  return {std::move(b),std::move(e)};
}

простой ряд для ряда для только. Может быть дополнен идеальной переадресацией.

передает C как контейнер, который может потребоваться продление жизни. Если передано как rvalue, копия сделана, в противном случае просто ссылка. Иное не используемый.

Следующая часть-это просто:

template<class It>
auto reverse_it(It it){
  return std::reverse_iterator<It>(std::move(it));
} 
template<class C>
auto backwards(C&&c){
  using std::begin; using std::end;
  auto b=begin(c), e=end(c);
  return range_for(
    reverse_it(e),reverse_it(b),
    std::forward<C>(c)
  );
}

это непроверено, но должно работать.

один важный тест гарантирует, что он работает, когда вы кормите rvalue vec, как:

 for(auto x:backwards(make_vec()))

работает - вот что беспорядок вокруг хранения C - примерно. Он также предполагает, что перемещенные итераторы контейнера имеют итераторы, которые ведут себя хорошо.


Boost предлагает функцию с именем отменено, который можно использовать с диапазон C++ 11 на основе цикла как описывает Якк в ответ:

for(int i : reverse(A))
{
  // code
}

или

for(int i : A | reversed)
{
  // code
}