具有自定义步骤的循环的C ++范围 [英] C++ range for loops with custom step

查看:60
本文介绍了具有自定义步骤的循环的C ++范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在c ++ 11中,您可以遍历具有for循环范围的容器:

In c++ 11 you can iterate over a container with range for loops :

for (auto i : vec) { /* do stuff */ }

除了反向迭代的缺点并不明显( C ++ 11相反基于范围的for循环),这也受到您无法为迭代定义自定义步骤这一事实的限制.

Besides the drawback that iterating in reverse is not that obvious (C++11 reverse range-based for-loop) it is also limited by the fact that you cannot define a custom step for the iteration.

有办法吗?我无法解决这个问题,但是可以想象像

Is there a way to do it? I can't get my mind around it, but imagine an adaptor like

template<typename T>
struct step
{
    T const &container;
    step( T const &cont, int aStep);
    // provide begin()  / end() member functions
    // maybe overload the ++ operator for the iterators ? 
};

for (auto i : step(vec, i)) {}

讨论是关于实现类似于Python生成器的语义 https://wiki.python.org/moin/Generators ,例如range()函数.请不要对此发表任何评论,这将如何增加代码的复杂性,没有人回过头来为Python编写循环,即使在C ++中不是这种情况(我应该再说一遍:事实并非如此)在c ++中)我想探索写作方式

The discussion is about achieving semantics similar to Pythons generators https://wiki.python.org/moin/Generators eg the range() function. Please don't make pointless comments on how this would increase code complexity, no one ever went back to hand written for loops in Python, and even though this is not the case in C++ (I should say that again: this is NOT the case in c++) I wanted to explore ways to write

for (auto i : range(vec, step))

因为新标准提供了使用这种语法的便利.range()函数将是一次性的工作,并且代码的用户将不必担心植入的细节

since the new standard provides the facilities to use such syntax. The range() function would be a one time effort and the user of the code would not have to worry about the specifics of the imlpementation

推荐答案

范围-基于

for ( range_declaration : range_expression ) loop_statement

只需要一个 begin 和一个 end 迭代器,就对它们执行前缀 operator ++ :

just takes a begin and an end iterator, performing prefix operator++ on them like this:

{
  auto && __range = range_expression ;
  for (auto __begin = begin_expr, __end = end_expr;
       __begin != __end; ++__begin)
  {
    range_declaration = *__begin;
    loop_statement
  }
} 

其中 begin_expr end_expr 做正确的事"(有关详细信息,请参见上面的链接).您可以做的是提供一个 range_expression 代理对象,以便其迭代器执行您想要的操作.一个很好的例子是 Boost的范围适配器库:

Where begin_expr and end_expr "do the right thing" (see link above for the details). What you can do, is supply a proxy object as range_expression, so that its iterators do what you want. A prime example is Boost's range adaptors library:

#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/reversed.hpp>

#include <iostream>
#include <vector>

int main()
{
  std::vector<int> input = {1,2,3,4,5,6,7,8,9,10};

  for(const auto& element : boost::adaptors::reverse(input))
    std::cout << element << '\n';
  std::cout << '\n';

  for(const auto& element : boost::adaptors::stride(input,2))
    std::cout << element << '\n';
}

在此处进行实时演示.

这与Python range 非常相似,并且功能几乎相同(甚至更多).您可以轻松编写自己的适配器,例如此问题的答案.

This is quite similar and virtually equally (if not more) powerful to Python range. You can easily write your own adaptors, see e.g. the answers to this question.

这篇关于具有自定义步骤的循环的C ++范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆