https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119501
Bug ID: 119501
Summary: std::ranges::copy_n advances InputIterator one more
time than necessary
Product: gcc
Version: 14.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: felip_assis at hotmail dot com
Target Milestone: ---
It seems that the fixed bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50119
reemerged in the Constrained Algorithms library (namespace std::ranges).
This is not a regression, std::copy_n works as expected, but now
std::ranges::copy_n has the issue, making it not only surprising, but also
internally inconsistent.
The problem is that, with istream_iterator, "the actual read operation is
performed when the iterator is incremented, not when it is dereferenced"
(https://en.cppreference.com/w/cpp/iterator/istream_iterator), but the
implementation of std::ranges::copy_n increments the iterator once more than
needed, adding an unexpected read operation. So, while its interface was
carefully planned to allow usage of input iterators, it fails with the
prototypical one, that is part of the standard.
Test program:
```
#include <algorithm>
#include <vector>
#include <sstream>
#include <iterator>
#include <iostream>
int main()
{
std::istringstream s("1 2 3 4 5");
std::vector<int> v;
char c;
std::istream_iterator<int> it{s};
std::ranges::copy_n(it, 3, back_inserter(v));
s >> c;
copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << c << '\n';
}
```
Compilation:
$ g++ -std=c++23 test.cpp
Output with GCC 14.2.1 (unexpected):
1 2 3 5
Output changing "std::ranges::copy_n" to "std::copy_n" (expected):
1 2 3 4
I admit that I have come up with a robust workaround, but the code is no longer
expressive:
```
it = std::ranges::copy_n(it, 3 - 1, back_inserter(v)).in;
v.push_back(*it);
s >> c;
```
Output of the workaround (expected):
1 2 3 4