libstdc++: Use std::move for iterator in ranges::fill [PR117094]

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.
This commit is contained in:
Jonathan Wakely 2024-10-13 22:48:43 +01:00 committed by Jonathan Wakely
parent d8ef4471cb
commit 03623fa91f
No known key found for this signature in database
2 changed files with 35 additions and 1 deletions

View File

@ -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>)
{

View File

@ -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();
}