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

Reply via email to