在C++中,如何使用for_each反向迭代数组?

use*_*954 8 stl c++11 stdarray

在C++ 11中,使用lambda/for_each,我们如何从end迭代一个数组?

我尝试了以下,但都导致无限循环:

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

for_each (A.rend(), A.rbegin(), [](int i) {
    ...
});
Run Code Online (Sandbox Code Playgroud)

任何的想法?谢谢.

P0W*_*P0W 22

你错过了吗?

翻转你的rbegin&rend

for_each (A.rbegin(), A.rend(), [](int i) {
    ...
});
Run Code Online (Sandbox Code Playgroud)

增加反向迭代器会将它们移向容器的开头


Yak*_*ont 6

std::for_each( A.rbegin(), A.rend(), [](int i) { /*code*/ } ); 是简单的解决方案.

我改为编写backwards了一个序列,使用free 和函数(使用附近的声明和完整的ADL)从中提取beginend迭代器,在它们周围创建反向迭代器,然后返回带有这两个反向迭代器的序列.beginendstd::beginstd::end using

它有点整洁,因为你得到这样的语法:

for( int i : backwards(A) ) {
  // code
}
Run Code Online (Sandbox Code Playgroud)

我觉得比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)};
}
Run Code Online (Sandbox Code Playgroud)

仅适用于范围的简单范围.可以通过完美转发进行扩充.

C作为可能需要终身延伸的容器传递.如果作为右值传递,则复制,否则只是引用.否则不使用它.

下一部分很简单:

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)
  );
}
Run Code Online (Sandbox Code Playgroud)

这是未经测试但应该有效.

一个重要的测试是确保它在你给rvalue vec喂食时起作用:

 for(auto x:backwards(make_vec()))
Run Code Online (Sandbox Code Playgroud)

工作 - 这就是存储的混乱C所在.它还假设移动的容器迭代器具有行为良好的迭代器.