范围的递归函数(从范围 v3 开始)导致编译发散:为什么


出于

某种原因,下面列表中的代码导致 clang++ 和 g++ 使用 100% CPU,并填满内存,直到我的系统挂起。

请注意,这是一个演讲的玩具示例。我知道accumulatetransform是执行此操作的标准方法,但此代码是推理链中的中间点。

#include <iostream>
#include <range/v3/all.hpp>
using namespace ranges;
template <typename F, typename R, typename T>
T rec_map_sum(F f, R r, T tally) {
  if (ranges::begin(r) == ranges::end(r))
    return tally;
  else {
    auto r_head = *ranges::begin(r);
    auto r_tail = r | view::drop(1);
    return rec_map_sum(f, r_tail, tally + f(r_head));
    // this also crashes:
    // return rec_map_sum(f, r[{1, end}], tally + f(r_head));
  }
}
int main() {
  std::cout << rec_map_sum([](int x) { return x * x; }, view::iota(0, 10), 0)
            << std::endl;
  return 0;
}

rec_map_sum 函数旨在实现一个递归,该递归采用整数范围和一元函数,将函数逐个元素应用于范围,并生成映射元素的总和。

有两个问题:(1(发散行为的原因是什么,(2(我应该如何制作和传递尾视图,以使编译不会崩溃?

Jarod42指出了这个问题,但解决方案非常简单。您需要一个可以采用任何范围的文字擦除视图。幸运的是,这样的事情存在。将代码更改为:

template <typename F, typename R, typename T>
T rec_map_sum(F f, R r, T tally) {
  auto r2 = any_view<T>{r};
  if (ranges::begin(r2) == ranges::end(r2))
    return tally;
  else {
    auto r_head = *ranges::begin(r2);
    auto r_tail = r2 | view::drop(1);
    return rec_map_sum(f, r_tail, tally + f(r_head));
  }
}

这打印了 285。

最新更新