Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ back method for sub-range not found after chunking list

I came across this weird behaviour where if you create a chunked view, by 2 elements, of a list and then try to print the front and the back while in a ranged for loop, the front method will work, but the back method won't. It will produce a compiler error saying that instantiating the .back() method requires a bidirectional iterator. Am I missing something?

Code to reproduce the error

#include <iostream>
#include <list>
#include <ranges>
#include <vector>

int main() {
  std::list<int> nums_list = {0, 1, 2, 3, 4, 5};

  auto rng = nums_list | std::views::chunk(2);
  for (auto pair : rng) {
    std::cout << pair.front(); // Front will work normally
    std::cout << pair.back();  // No matching member function for 'back'.
  }
}

I tried it with vector as well and it worked as expected.

like image 431
ciuckc Avatar asked Nov 01 '25 19:11

ciuckc


1 Answers

It will produce a compiler error saying that instantiating the .back() method requires a bidirectional iterator. Am I missing something?

The front() member is provided only if the view inherited from view_interface satisfies forward_range, and the back() member is provided if both common_range and bidirection_range are satisfied.

std::list satisfies common_range and bidirectional_range, so rng is also common_range and bidirectional_range†, which allows you to use back() on it, for example:

std::list<int> nums_list = {0, 1, 2, 3, 4, 5};
auto rng = nums_list | std::views::chunk(2);
auto back = rng.back();

However, the value type of rng, i.e. pair in your example, is specified as decltype(views::take(subrange(current_, end_), n_))†, where current_, end_ are the iterators of the std::list.

Since std::list::iterator cannot be subtracted, that is to say, they do not satisfy sized_sentinel_for, this makes the subrange they construct not sized_range, which ultimately results in take_view not being common_range, so its back() synthesis fails.


† To support back(), chunk_view also needs to know the size of the underlying range to find the starting position of the last chunk. This is not a problem for std::list as it is a sized_range.

views::take is used here to automatically handle the situation where the number of the last chunk is less than n.

like image 188
康桓瑋 Avatar answered Nov 04 '25 10:11

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!