Search code examples
c++c++20std-ranges

Why cant I chain after std::ranges::views::join?


I recently discovered the ranges stdandard library and encountered a strange behavior. When chaining multiple range adaptors, I can't chain after using std::ranges::views::join:

vec | std::ranges::views::slide(2) | std::ranges::views::join

works as intended, but

vec | std::ranges::views::slide(2) | std::ranges::views::join | std::ranges::views::slide(2)

will result in compilation error:

error: no match for 'operator|' (operand types are 'std::ranges::join_view<std::ranges::slide_view<std::ranges::ref_view<std::vector<int> > > >' and 'std::ranges::views::__adaptor::_Partial<std::ranges::views::_Slide, int>')
  265 |   vec | std::ranges::views::slide(2) | std::ranges::views::join | std::ranges::views::slide(2);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                      |                                                     |
      |                                      |                                                     std::ranges::views::__adaptor::_Partial<std::ranges::views::_Slide, int>
      |                                      std::ranges::join_view<std::ranges::slide_view<std::ranges::ref_view<std::vector<int> > > >

Why is that? and what do I have to do to make multiple joins work?

Thanks in advance!


Solution

  • slide_view requires forward_range since the elements need to be traversed more than once.

    This is not the case for join_view in your case, because the latter joins a nested range whose elements are prvalue ranges (slide_view acts on vector will produce a range whose element type is prvalue span as "window"), which makes it just an input_range.

    The constraints are not satisfied so compilation fails.