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