【问题标题】:C++ range for loops with custom step具有自定义步骤的循环的 C++ 范围
【发布时间】:2014-02-02 22:58:22
【问题描述】:

在 c++ 11 中,您可以使用范围 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)) {}

编辑:

讨论是关于实现类似于 Python 生成器https://wiki.python.org/moin/Generators 的语义,例如 range() 函数。请不要对这将如何增加代码复杂性做出毫无意义的 cmets,没有人会回头用 Python 编写 for 循环,即使在 C++ 中不是这种情况(我应该再说一遍:不是这种情况在 c++ 中)我想探索编写方法

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

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

【问题讨论】:

标签: c++


【解决方案1】:

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的答案。

【讨论】:

    【解决方案2】:

    这个 C++-11 特性主要是最常见情况的便捷快捷方式。如果您想充分利用 C/C++ for 循环的全部荣耀,您最好采用长期(遗留)方式。尝试像定义奇怪的增量运算符这样的聪明技巧只会让你温柔的读者(通常是几周后的你自己)完全糊涂。试想一下,如果在其他地方的一周内您需要增加一,而不是二,并且您没有注意到“智能”增加,会发生什么......这是引入微妙的、不可能发现错误的好方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-23
      • 2013-07-30
      • 2015-03-09
      • 2021-12-30
      • 1970-01-01
      • 2014-07-11
      • 2015-10-01
      • 1970-01-01
      相关资源
      最近更新 更多