1

I'm writing a proxy iterator using Boost.STLInterfaces. It has inline friend constexpr void iter_swap(iter lhs, iter rhs) noexcept. ranges::sort requires, among others, std::indirectly_swappable, which requires ranges::iter_swap for the iterator. But with gcc-11.2.0 the call stack looks something like

1  my::swap                                item.hpp       91  
2  std::iter_swap<my::iter, my::iter>      stl_algobase.h 182 
3  std::__move_median_to_first<...>        stl_algo.h     92  
4  std::__unguarded_partition_pivot<...>   stl_algo.h     1904
5  std::__introsort_loop<...>              stl_algo.h     1938
6  std::__sort<...>                        stl_algo.h     1954
7  std::sort<...>                          stl_algo.h     4875
8  std::ranges::__sort_fn::operator()<...> ranges_algo.h  2029
9  std::ranges::__sort_fn::operator()<...> ranges_algo.h  2040
10 operator()                              sort.cpp       68  
11 main                                    sort.cpp       82  

i.e. ranges::sort calls std::sort, which does not use the customization, but calls std::iter_swap explicitly. It still works because of the hidden friend swap for the reference type, though.

What is needed to make sure ranges::sort uses the customization?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
SD57
  • 73
  • 7
  • So your question is why `ranges::sort` requires `ranges::iter_swap` to be well-formed but does not use it? – 康桓瑋 Nov 23 '21 at 07:34
  • Am I using the right way to customize? std::ranges::sort is supposed to support proxy iterators, while std::sort doesn't. What is the difference other than iter_swap? In my case they do the same. – SD57 Nov 23 '21 at 09:20
  • 3
    In fact, the implementation of `ranges::sort` should not use `std::sort` directly since the iterator system which the two are based on is different. – 康桓瑋 Nov 23 '21 at 10:35
  • To add to what @康桓瑋 said, if you look at the sources of libstdc++, `std::ranges::sort` calls to `std::sort`, but `std::sort` does not support proxy references. So this is a bug. Notice that it is also true for `std::ranges::stable_sort` and `std::ranges::partial_sort`. But e.g. `std::ranges::partition` is implemented in terms of `std::ranges::iter_swap` and does not call `std::partition`. So you are not very far from a range-compatible quicksort... – Bérenger Feb 15 '22 at 23:36
  • See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104561 – Bérenger Feb 16 '22 at 00:15

0 Answers0