diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-10-13 22:48:43 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2024-10-14 10:55:50 +0100 |
commit | 03623fa91ff36ecb9faa3b55f7842a39b759594e (patch) | |
tree | 061355f4468d8f7ed2337a42c4f81ae87e12a7f6 | |
parent | d8ef4471cb9c9f86784b62424a215ea42173bfe1 (diff) | |
download | gcc-03623fa91ff36ecb9faa3b55f7842a39b759594e.zip gcc-03623fa91ff36ecb9faa3b55f7842a39b759594e.tar.gz gcc-03623fa91ff36ecb9faa3b55f7842a39b759594e.tar.bz2 |
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.
-rw-r--r-- | libstdc++-v3/include/bits/ranges_algobase.h | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc | 34 |
2 files changed, 35 insertions, 1 deletions
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index 3c8d461..0345ea8 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 126515e..7cae99f 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(); } |