Range recursive function (of range-v3) causes compilation to diverge: why?

For some reason, the code in the list below makes clang ++ and g ++ use 100% CPU and fill up memory until my system freezes.

Note , this is an example of a conversation game. I know that accumulate

and transform

is the standard way to do this, but this code is an intermediate point in the chain of reasoning.

#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;
}

      

The function is rec_map_sum

designed to implement recursion, which takes a range of integers and a unary function, applies an element to the range, and produces the sum of the displayed elements.

I have two questions: (1) what is the reason for the diverging behavior, and (2) how do I make and pass the tail representation so that the compilation doesn't work?

+3


source to share


1 answer


The problem is pointed out by Jarod42, but the solution is pretty simple. You need an erasable view type that can take any range. Fortunately, such a thing exists . Change your code to:

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

      



Will print 285.

+2


source







All Articles