std::for_each( A.rbegin(), A.rend(), [](int i) { /*code*/ } ); 是简单的解决方案。
我写了backwards,它接受一个序列,使用免费的begin和end函数从中提取begin和end迭代器(使用std::begin和std::endusing附近的声明——完整的 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)};
}
range for only 的简单范围。可以通过完美转发来增强。
传递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)
);
}
这是未经测试的,但应该可以工作。
一个重要的测试是确保它在您输入右值 vec 时能正常工作,例如:
for(auto x:backwards(make_vec()))
有效——这就是存储C 的麻烦所在。它还假设移动的容器迭代器具有表现良好的迭代器。