https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118209
Bug ID: 118209 Summary: ranges::sort doesn't use iter_move, cannot sort zip of move-only type Product: gcc Version: 14.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: arthur.j.odwyer at gmail dot com Target Milestone: --- Bug #105609 is related, i.e. it's about using std::move(*it) where ADL iter_move(it) is required; but I think this new one differs enough to file it separately. This one transitively affects make_heap and partial_sort. This initially came from StackOverflow: https://stackoverflow.com/questions/12227474/can-iter-swap-be-specialised/75535132?noredirect=1#comment139852610_75535132 // https://godbolt.org/z/jqYE9Tnqe #include <algorithm> #include <ranges> #include <vector> struct F { int a = -1; explicit F(int d) : a(d) { } F(const F&) = delete; F(F&& o) : a(o.a) { } void operator=(const F&) = delete; F& operator=(F&& o) { a = o.a; return *this; } auto operator<=>(const F&) const = default; }; int main() { int a[] = {3,2,1}; std::vector<F> v(a, a+3); // sorting v is OK std::ranges::sort(v); // sorting zip(v) doesn't compile std::ranges::sort(std::views::zip(v)); } include/c++/15.0.0/bits/stl_heap.h:355:15: error: no viable conversion from 'typename std::remove_reference<tuple<F &>>::type' (aka 'std::tuple<F &>') to '_ValueType' (aka 'std::tuple<F>') 355 | _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent)); | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This happens inside __make_heap, called from __partial_sort. The problem is that it's calling `std::move(*iter)` to get an xvalue zip_view::reference, which then converts to an lvalue F, which can't be copied because F is move-only. What we need instead is to call zip_view::iterator's ADL `iter_move(iter)`, to give us an xvalue F directly. libc++ and MS STL both handle this OK.