https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119022

            Bug ID: 119022
           Summary: ranges::inplace_merge should check for
                    iterator_concept, not iterator_category
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: curdeius at gmail dot com
  Target Milestone: ---

Related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100070

It's related to the above bug report, but it concerns algorithms, an example is
std::ranges::inplace_merge.
It delegates the work to std::inplace_merge, but for some views (e.g. zip_view,
iota_view), their iterators are of (C++17) iterator_category input_iterator_tag
only, while of (C++20) iterator_concept being possibly higher (e.g.
random_access_iterator_tag if all zipped ranges are random-access).

Reproduce: https://godbolt.org/z/f5b1vh79h

```
#include <algorithm>
#include <concepts>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> a{1, 2, 1, 3, 4, 5, 6};
    std::vector<long> b{13, 14, 11, 12, 13, 15, 16, 17};

    auto r = std::views::zip(a, b);
    static_assert(std::ranges::random_access_range<decltype(a)>);
    static_assert(std::ranges::random_access_range<decltype(b)>);
    static_assert(std::ranges::random_access_range<decltype(r)>);

    std::ranges::rotate(r, r.begin() + 2);
    std::ranges::inplace_merge(r, r.begin() + 2);
}
```

It fails on libstdc++, works on libc++.
In libstdc++, `iterator_category` is always used.
In libc++, `iterator_concept` is used for constrained algorithms.

Cf.
https://github.com/llvm/llvm-project/blob/main/libcxx/include/__algorithm/iterator_operations.h#L54
used by
https://github.com/llvm/llvm-project/blob/main/libcxx/include/__algorithm/inplace_merge.h#L134
used by
https://github.com/llvm/llvm-project/blob/main/libcxx/include/__algorithm/ranges_inplace_merge.h#L47

Reply via email to