LGTM On Mon, 14 Oct 2024, Jonathan Wakely wrote:
> Tested x86_64-linux. > > -- >8 -- > > Input iterators aren't required to be copyable. > > libstdc++-v3/ChangeLog: > > PR libstdc++/117094 > * include/bits/ranges_algobase.h (__fill_fn): Use std::move for > iterator that might not be copyable. > * testsuite/25_algorithms/fill/constrained.cc: Check > non-copyable iterator with sized sentinel. > --- > libstdc++-v3/include/bits/ranges_algobase.h | 2 +- > .../25_algorithms/fill/constrained.cc | 34 +++++++++++++++++++ > 2 files changed, 35 insertions(+), 1 deletion(-) > > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h > b/libstdc++-v3/include/bits/ranges_algobase.h > index 3c8d46198c5..0345ea850a4 100644 > --- a/libstdc++-v3/include/bits/ranges_algobase.h > +++ b/libstdc++-v3/include/bits/ranges_algobase.h > @@ -592,7 +592,7 @@ namespace ranges > if constexpr (sized_sentinel_for<_Sent, _Out>) > { > const auto __len = __last - __first; > - return ranges::fill_n(__first, __len, __value); > + return ranges::fill_n(std::move(__first), __len, __value); > } > else if constexpr (is_scalar_v<_Tp>) > { > diff --git a/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc > b/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc > index 126515eddca..7cae99f2d5c 100644 > --- a/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc > +++ b/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc > @@ -83,9 +83,43 @@ test02() > return ok; > } > > +void > +test03() > +{ > + // Bug libstdc++/117094 - ranges::fill misses std::move for output_iterator > + > + // Move-only output iterator > + struct Iterator > + { > + using difference_type = long; > + Iterator(int* p) : p(p) { } > + Iterator(Iterator&&) = default; > + Iterator& operator=(Iterator&&) = default; > + int& operator*() const { return *p; } > + Iterator& operator++() { ++p; return *this; } > + Iterator operator++(int) { return Iterator(p++ ); } > + int* p; > + > + struct Sentinel > + { > + const int* p; > + bool operator==(const Iterator& i) const { return p == i.p; } > + long operator-(const Iterator& i) const { return p - i.p; } > + }; > + > + long operator-(Sentinel s) const { return p - s.p; } > + }; > + static_assert(std::sized_sentinel_for<Iterator::Sentinel, Iterator>); > + int a[2]; > + std::ranges::fill(Iterator(a), Iterator::Sentinel{a+2}, 999); > + VERIFY( a[0] == 999 ); > + VERIFY( a[1] == 999 ); > +} > + > int > main() > { > test01(); > static_assert(test02()); > + test03(); > } > -- > 2.46.2 > >