ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Calling back() on strided range does not return the correct last value in range

jlconlin opened this issue · comments

When calling back() on a range that has been run through ranges::view::stride( i ), the value returned is not correct. In our (@jlconlin and @apmccartney) testing, this happens when the size of the range is not evenly divisible by the argument to ranges::view::stride.

However, when using the bracket operator [] and passing size()-1 as the argument, the correct value is returned.

Here is an example that demonstrates the issue (also implemented on wandbox.com):

// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <cstdlib>
#include "range/v3/all.hpp"
#include <vector>

using namespace std;

int main()
{
  cout << "Hello, Wandbox!" << endl;
  auto r = ranges::view::iota( 0, 12 );
  cout << r << endl;
  cout << "\tsize:  " << r.size() << endl;
  cout << "\tfront: " << r.front() << endl;
  cout << "\t[ 0 ]: " << r.front() << endl;
  cout << "\tback:  " << r.back() << endl;
  cout << "\t[ 11 ]: " << r[ 11 ] << endl;
  cout << "\t[ s-1 ]: " << r[ r.size() - 1 ] << endl;
  
  cout << "\nEvenly divisible stride: " << endl;
  auto strided1 = r | ranges::view::stride(3);
  cout << strided1 << endl;
  cout << "\tsize:  " << strided1.size() << endl;
  cout << "\tfront: " << strided1.front() << endl;
  cout << "\t[ 0 ]: " << strided1.front() << endl;
  cout << "\tback:  " << strided1.back() << endl;
  cout << "\t[ 3 ]: " << strided1[ 3 ] << endl;
  cout << "\t[ s-1 ]: " << strided1[ strided1.size() - 1 ] << endl;
  
  cout << "\nNot evenly divisible stride: " << endl;
  auto strided2 = r | ranges::view::stride(5);
  cout << strided2 << endl;
  cout << "\tsize:  " << strided2.size() << endl;
  cout << "\tfront: " << strided2.front() << endl;
  cout << "\t[ 0 ]: " << strided2.front() << endl;
  cout << "\tback:  " << strided2.back() << endl;
  cout << "\t[ 2 ]: " << strided2[ 2 ] << endl;
  cout << "\t[ s-1 ]: " << strided2[ strided2.size() - 1 ] << endl;
}

Output:

Hello, Wandbox!
[0,1,2,3,4,5,6,7,8,9,10,11]
	size:  12
	front: 0
	[ 0 ]: 0
	back:  11
	[ 11 ]: 11
	[ s-1 ]: 11

Evenly divisible stride: 
[0,3,6,9]
	size:  4
	front: 0
	[ 0 ]: 0
	back:  9
	[ 3 ]: 9
	[ s-1 ]: 9

Not evenly divisible stride: 
[0,5,10]
	size:  3
	front: 0
	[ 0 ]: 0
	back:  4
	[ 2 ]: 10
	[ s-1 ]: 10