具有自定义步骤的循环的C 范围

C++ range for loops with custom step

本文关键字:循环 范围 自定义      更新时间:2023-10-16

在C 11中,您可以在具有循环范围的容器上迭代:

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

除了反向迭代并不是那么明显的缺点(C 11反向范围的for-loop)外,它还受到您无法为迭代定义自定义步骤的事实。

有办法做到吗?我无法确定它,但想象一个适配器

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)) {}

编辑:

讨论是关于实现类似于Pythons Generator的语义的讨论https://wiki.python.org/moin/generators,例如range()函数。请不要对这会如何增加代码复杂性发表毫无意义在C 中)我想探索写作的方法

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

由于新标准提供了使用这种语法的设施。range()函数将是一次性的努力,代码的用户不必担心Imlpementation的细节

基于范围的

for ( range_declaration : range_expression ) loop_statement

只采用beginend迭代器,在此上执行前缀operator++

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

其中 begin_exprend_expr"做正确的事情"(有关详细信息,请参见上面的链接)。您能做的就是将代理对象作为range_expression提供,以便其迭代器完成您想要的工作。一个典型的例子是Boost的范围适配器库:

#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非常相似,实际上(如果不是更多的话)。您可以轻松编写自己的适配器,请参阅例如这个问题的答案。

此C -11功能主要是最常见情况的便利捷径。如果您想利用C/C for环路的完整荣耀,最好以漫长的(遗产)方式来做。尝试智能技巧(例如定义奇怪的增量操作员)只会导致您的温柔读者(几周后您自己经常)完全感到困惑。试想一下,如果您需要在其他地方的一周中,您需要以一个而不是两个,而您不会注意到"智能"增量...这是一种介绍微妙的,不可能发现错误的好方法。