On Tue, Feb 17, 2026 at 11:44 AM Jonathan Wakely <[email protected]> wrote:
> > > On Mon, 16 Feb 2026, 19:48 Avi Kivity, <[email protected]> wrote: > >> >> >> On Mon, Feb 16, 2026 at 8:29 PM Jonathan Wakely <[email protected]> >> wrote: >> >>> On Mon, 16 Feb 2026 at 17:59, Avi Kivity <[email protected]> wrote: >>> > >>> > std::uninitialized_move{,_n} delegates to the corresponding >>> > std::uninitialized_copy() variant after wrapping with a move >>> > iterator, but the std::uninitialized_copy() doesn't unwrap the >>> > move iterator, therefore losing the memcpy optimization if the >>> > iterators were just pointers. >>> > >>> > Fix this by unwrapping the move iterator using __miter_base(). To >>> > prevent some greedy_ops tests starting to fail by consuming the >>> > pointer difference, we have to unwrap the move iterator before >>> computing >>> > the iterator difference as well. >>> > >>> > libstdc++v3/Changelog: >>> > >>> > PR libstdc++/121789 >>> > * include/bits/stl_uninitialized.h (uninitialized_copy): >>> > Unwrap move iterators >>> > * >>> testsuite/20_util/specialized_algorithms/uninitialized_move/121789.cc: >>> > New test. >>> > --- >>> > >>> > Disclosure: I was assisted by AI. >>> > >>> > libstdc++-v3/include/bits/stl_uninitialized.h | 8 ++-- >>> > .../uninitialized_move/121789.cc | 37 +++++++++++++++++++ >>> > 2 files changed, 42 insertions(+), 3 deletions(-) >>> > create mode 100644 >>> libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/121789.cc >>> > >>> > diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h >>> b/libstdc++-v3/include/bits/stl_uninitialized.h >>> > index 82e4ba2ff7b..fa9d896fefc 100644 >>> > --- a/libstdc++-v3/include/bits/stl_uninitialized.h >>> > +++ b/libstdc++-v3/include/bits/stl_uninitialized.h >>> > @@ -273,11 +273,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>> > // We cannot tell when this condition is true in general, >>> > // so we rely on the __memcpyable trait. >>> > >>> > #if __cplusplus >= 201103L >>> > using _Dest = decltype(std::__niter_base(__result)); >>> > - using _Src = decltype(std::__niter_base(__first)); >>> > + using _Src = >>> decltype(std::__miter_base(std::__niter_base(__first))); >>> > using _ValT = typename >>> iterator_traits<_ForwardIterator>::value_type; >>> > >>> > #if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 >>> > if consteval { >>> > return std::__do_uninit_copy(__first, __last, __result); >>> > @@ -285,16 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >>> > #endif >>> > if constexpr (!__is_trivially_constructible(_ValT, >>> decltype(*__first))) >>> > return std::__do_uninit_copy(__first, __last, __result); >>> > else if constexpr (__memcpyable<_Dest, _Src>::__value) >>> > { >>> > - ptrdiff_t __n = __last - __first; >>> > + ptrdiff_t __n >>> > + = std::__miter_base(std::__niter_base(__last)) >>> > + - std::__miter_base(std::__niter_base(__first)); >>> >>> This change seems completely unnecessary (I blame the AI assistance). >>> >>> >> It is necessary. Without it, 23_containers/vector/types/1.cc will not >> compile since greedy_ops' >> operator- will fight with the move iterator's operator-. I mentioned it >> in the commit changelog. >> > > But that's more evidence that the greedy_ops tests are invalid C++. > Shall I send a patch to remove them? > Or if we still care about them, we should fix move_iterator. > > I can't make that call. > We need to be able to subtract two move_iterator objects. That's a > requirement for random access iterators. > There's this: // DR 685. template<typename _IteratorL, typename _IteratorR> [[__nodiscard__]] inline _GLIBCXX17_CONSTEXPR auto operator-(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) -> decltype(__x.base() - __y.base()) { return __x.base() - __y.base(); } But apparently greedy_ops matches our expression with higher precedence. > > > >> Perhaps std::distance() is better here. >> > (probably std::distance will fail when it calls operator-)
