diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-02-27 13:27:17 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-02-28 21:35:27 +0000 |
commit | 3866ca796d5281d33f25b4165badacf8f198c6d1 (patch) | |
tree | f258fc80ee51dece3bc84c559d300d42c63ce9c8 | |
parent | a9cfcd0d9e3780c71442057f636f62a7142056cb (diff) | |
download | gcc-3866ca796d5281d33f25b4165badacf8f198c6d1.zip gcc-3866ca796d5281d33f25b4165badacf8f198c6d1.tar.gz gcc-3866ca796d5281d33f25b4165badacf8f198c6d1.tar.bz2 |
libstdc++: Fix ranges::move and ranges::move_backward to use iter_move [PR105609]
The ranges::move and ranges::move_backward algorithms are supposed to
use ranges::iter_move(iter) instead of std::move(*iter), which matters
for an iterator type with an iter_move overload findable by ADL.
Currently those algorithms use std::__assign_one which uses std::move,
so define a new ranges::__detail::__assign_one helper function that uses
ranges::iter_move.
libstdc++-v3/ChangeLog:
PR libstdc++/105609
* include/bits/ranges_algobase.h (__detail::__assign_one): New
helper function.
(__copy_or_move, __copy_or_move_backward): Use new function
instead of std::__assign_one.
* testsuite/25_algorithms/move/constrained.cc: Check that
ADL iter_move is used in preference to std::move.
* testsuite/25_algorithms/move_backward/constrained.cc:
Likewise.
3 files changed, 78 insertions, 6 deletions
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index eceb859..a08f659b 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -188,6 +188,20 @@ namespace ranges inline constexpr __equal_fn equal{}; +namespace __detail +{ + template<bool _IsMove, typename _OutIter, typename _InIter> + [[__gnu__::__always_inline__]] + constexpr void + __assign_one(_OutIter& __out, _InIter& __in) + { + if constexpr (_IsMove) + *__out = ranges::iter_move(__in); + else + *__out = *__in; + } +} // namespace __detail + template<typename _Iter, typename _Out> struct in_out_result { @@ -291,14 +305,14 @@ namespace ranges __builtin_memmove(__result, __first, sizeof(_ValueTypeI) * __num); else if (__num == 1) - std::__assign_one<_IsMove>(__result, __first); + __detail::__assign_one<_IsMove>(__result, __first); return {__first + __num, __result + __num}; } } for (auto __n = __last - __first; __n > 0; --__n) { - std::__assign_one<_IsMove>(__result, __first); + __detail::__assign_one<_IsMove>(__result, __first); ++__first; ++__result; } @@ -308,7 +322,7 @@ namespace ranges { while (__first != __last) { - std::__assign_one<_IsMove>(__result, __first); + __detail::__assign_one<_IsMove>(__result, __first); ++__first; ++__result; } @@ -420,7 +434,7 @@ namespace ranges __builtin_memmove(__result, __first, sizeof(_ValueTypeI) * __num); else if (__num == 1) - std::__assign_one<_IsMove>(__result, __first); + __detail::__assign_one<_IsMove>(__result, __first); return {__first + __num, __result}; } } @@ -432,7 +446,7 @@ namespace ranges { --__tail; --__result; - std::__assign_one<_IsMove>(__result, __tail); + __detail::__assign_one<_IsMove>(__result, __tail); } return {std::move(__lasti), std::move(__result)}; } @@ -445,7 +459,7 @@ namespace ranges { --__tail; --__result; - std::__assign_one<_IsMove>(__result, __tail); + __detail::__assign_one<_IsMove>(__result, __tail); } return {std::move(__lasti), std::move(__result)}; } diff --git a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc index 587b2f3..e2b45b0 100644 --- a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc @@ -204,6 +204,35 @@ test05() VERIFY( ranges::equal(v, (int[]){1,2,3,0}) ); } +namespace pr105609 +{ + struct I { + using value_type = int; + using difference_type = std::ptrdiff_t; + int operator*() const; + I& operator++(); + I operator++(int); + I& operator--(); + I operator--(int); + bool operator==(I) const; + friend int& iter_move(const I&); + }; +} + +void +test06(pr105609::I i) +{ + // PR libstdc++/105609 + // ranges::move should use ranges::iter_move instead of std::move + struct O { + O(int&) { } + O(int&&) = delete; + }; + + O* o = nullptr; + std::ranges::move(i, i, o); +} + int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc index 8f6fd45..4d94d38 100644 --- a/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc @@ -160,6 +160,35 @@ test03() return ok; } +namespace pr105609 +{ + struct I { + using value_type = int; + using difference_type = std::ptrdiff_t; + int operator*() const; + I& operator++(); + I operator++(int); + I& operator--(); + I operator--(int); + bool operator==(I) const; + friend int& iter_move(const I&); + }; +} + +void +test04(pr105609::I i) +{ + // PR libstdc++/105609 + // ranges::move should use ranges::iter_move instead of std::move + struct O { + O(int&) { } + O(int&&) = delete; + }; + + O* o = nullptr; + std::ranges::move_backward(i, i, o); +} + int main() { |