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