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

时间:2014-02-02 22:58:23

标签: c++

在c ++ 11中,您可以遍历带有range for循环的容器:

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

除了反向迭代不那么明显(C++11 reverse range-based 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生成器https://wiki.python.org/moin/Generators的语义,例如range()函数。请不要对这会如何增加代码复杂性做出毫无意义的评论,没有人回过头来编写Python中的循环,尽管在C ++中并非如此(我应该再说一遍:情况并非如此)在c ++)我想探索写作方式

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

因为新标准提供了使用这种语法的工具。 range()函数是一次性的努力,代码的用户不必担心imlpementation的具体细节

2 个答案:

答案 0 :(得分:5)

Range-based for

for ( range_declaration : range_expression ) loop_statement

只需要一个begin和一个end迭代器,对它们执行前缀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'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';
}

Live demo here.

这与Python range非常相似,几乎同样(如果不是更多)强大。您可以轻松编写自己的适配器,例如, this question的答案。

答案 1 :(得分:-3)

这个C ++ - 11功能主要是最常见情况下的便捷快捷方式。如果你想充分利用C / C ++ for循环的全部荣耀,你最好采用长期(遗留)方式。尝试定义奇怪的增量运算符等聪明的技巧只会让你温和的读者(通常是几周后你自己)变得非常困惑。试想一下,如果在其他地方的某个星期你需要增加一个而不是两个,并且你没有注意到“聪明”的增量...这是一个很好的方式来引入微妙的,不可能发现错误。