Skip to content

Commit 3866ca7

Browse files
committed
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.
1 parent a9cfcd0 commit 3866ca7

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

libstdc++-v3/include/bits/ranges_algobase.h

+20-6
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ namespace ranges
188188

189189
inline constexpr __equal_fn equal{};
190190

191+
namespace __detail
192+
{
193+
template<bool _IsMove, typename _OutIter, typename _InIter>
194+
[[__gnu__::__always_inline__]]
195+
constexpr void
196+
__assign_one(_OutIter& __out, _InIter& __in)
197+
{
198+
if constexpr (_IsMove)
199+
*__out = ranges::iter_move(__in);
200+
else
201+
*__out = *__in;
202+
}
203+
} // namespace __detail
204+
191205
template<typename _Iter, typename _Out>
192206
struct in_out_result
193207
{
@@ -291,14 +305,14 @@ namespace ranges
291305
__builtin_memmove(__result, __first,
292306
sizeof(_ValueTypeI) * __num);
293307
else if (__num == 1)
294-
std::__assign_one<_IsMove>(__result, __first);
308+
__detail::__assign_one<_IsMove>(__result, __first);
295309
return {__first + __num, __result + __num};
296310
}
297311
}
298312

299313
for (auto __n = __last - __first; __n > 0; --__n)
300314
{
301-
std::__assign_one<_IsMove>(__result, __first);
315+
__detail::__assign_one<_IsMove>(__result, __first);
302316
++__first;
303317
++__result;
304318
}
@@ -308,7 +322,7 @@ namespace ranges
308322
{
309323
while (__first != __last)
310324
{
311-
std::__assign_one<_IsMove>(__result, __first);
325+
__detail::__assign_one<_IsMove>(__result, __first);
312326
++__first;
313327
++__result;
314328
}
@@ -420,7 +434,7 @@ namespace ranges
420434
__builtin_memmove(__result, __first,
421435
sizeof(_ValueTypeI) * __num);
422436
else if (__num == 1)
423-
std::__assign_one<_IsMove>(__result, __first);
437+
__detail::__assign_one<_IsMove>(__result, __first);
424438
return {__first + __num, __result};
425439
}
426440
}
@@ -432,7 +446,7 @@ namespace ranges
432446
{
433447
--__tail;
434448
--__result;
435-
std::__assign_one<_IsMove>(__result, __tail);
449+
__detail::__assign_one<_IsMove>(__result, __tail);
436450
}
437451
return {std::move(__lasti), std::move(__result)};
438452
}
@@ -445,7 +459,7 @@ namespace ranges
445459
{
446460
--__tail;
447461
--__result;
448-
std::__assign_one<_IsMove>(__result, __tail);
462+
__detail::__assign_one<_IsMove>(__result, __tail);
449463
}
450464
return {std::move(__lasti), std::move(__result)};
451465
}

libstdc++-v3/testsuite/25_algorithms/move/constrained.cc

+29
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,35 @@ test05()
204204
VERIFY( ranges::equal(v, (int[]){1,2,3,0}) );
205205
}
206206

207+
namespace pr105609
208+
{
209+
struct I {
210+
using value_type = int;
211+
using difference_type = std::ptrdiff_t;
212+
int operator*() const;
213+
I& operator++();
214+
I operator++(int);
215+
I& operator--();
216+
I operator--(int);
217+
bool operator==(I) const;
218+
friend int& iter_move(const I&);
219+
};
220+
}
221+
222+
void
223+
test06(pr105609::I i)
224+
{
225+
// PR libstdc++/105609
226+
// ranges::move should use ranges::iter_move instead of std::move
227+
struct O {
228+
O(int&) { }
229+
O(int&&) = delete;
230+
};
231+
232+
O* o = nullptr;
233+
std::ranges::move(i, i, o);
234+
}
235+
207236
int
208237
main()
209238
{

libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc

+29
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,35 @@ test03()
160160
return ok;
161161
}
162162

163+
namespace pr105609
164+
{
165+
struct I {
166+
using value_type = int;
167+
using difference_type = std::ptrdiff_t;
168+
int operator*() const;
169+
I& operator++();
170+
I operator++(int);
171+
I& operator--();
172+
I operator--(int);
173+
bool operator==(I) const;
174+
friend int& iter_move(const I&);
175+
};
176+
}
177+
178+
void
179+
test04(pr105609::I i)
180+
{
181+
// PR libstdc++/105609
182+
// ranges::move should use ranges::iter_move instead of std::move
183+
struct O {
184+
O(int&) { }
185+
O(int&&) = delete;
186+
};
187+
188+
O* o = nullptr;
189+
std::ranges::move_backward(i, i, o);
190+
}
191+
163192
int
164193
main()
165194
{

0 commit comments

Comments
 (0)