在C ++ 11中,使用lambda / for_each,我们如何从end迭代一个数组?
我尝试了以下内容,但两者都导致无限循环:
for_each (end(A), begin(A), [](int i) {
....
});
for_each (A.rend(), A.rbegin(), [](int i) {
...
});
有什么想法吗?谢谢。
答案 0 :(得分:21)
你错过了吗?
翻转您的rbegin
& rend
for_each (A.rbegin(), A.rend(), [](int i) {
...
});
增加反向迭代器会将它们移向容器的开头
答案 1 :(得分:6)
std::for_each( A.rbegin(), A.rend(), [](int i) { /*code*/ } );
是一个简单的解决方案。
我改为编写了backwards
来获取序列,使用免费的begin
和end
函数从中提取begin
和end
迭代器(附近的std::begin
和std::end
using
声明 - 完整的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
作为可能需要终身延长的容器传递。如果作为右值传递,则复制,否则只是引用。否则不使用它。
下一部分很简单:
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
的混乱局面。它还假设移动的容器迭代器具有行为良好的迭代器。
答案 2 :(得分:1)
Boost提供了一个名为reversed的功能,可以与C++ 11 range based for loop一起使用,正如Yakk在回答中所描述的那样:
for(int i : reverse(A))
{
// code
}
或
for(int i : A | reversed)
{
// code
}