使用 C++23 zip 视图对两个数组进行排序

Fed*_*dor 7 c++ std-ranges c++23

有一个相当典型的任务是同时对两个数组进行排序,假设数组的相同索引元素形成虚拟对,并对其进行排序。这样的问题至少在 10 年前就出现过:boost zip_iterator 和 std::sort

现在这个任务可以使用range-v3库来解决:

#include <array>
#include <range/v3/all.hpp>

int main() {
   auto x = std::array{ 3,   2,   4,   1 };
   auto y = std::array{'A', 'B', 'C', 'D'};
   ranges::sort( ranges::views::zip( x, y ) );
   // here x = {1,2,3,4}, y={'D','B','A','C'}
}
Run Code Online (Sandbox Code Playgroud)

在线演示: https: //gcc.godbolt.org/z/WGo4vGsx5

在 C++23 中出现了std::ranges::zip_view,我的期望是可以仅使用标准库编写相同的程序:

#include <array>
#include <ranges>
#include <algorithm>

int main() {
   auto x = std::array{ 3,   2,   4,   1 };
   auto y = std::array{'A', 'B', 'C', 'D'};
   std::ranges::sort( std::views::zip( x, y ) );
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,它会导致很长的编译错误。例如在海湾合作委员会:

...
/opt/compiler-explorer/gcc-trunk-20221127/include/c++/13.0.0/bits/ranges_algo.h:54:31: error: no matching function for call to '__invoke(std::ranges::less&, std::pair<int, char>&, std::pair<int&, char&>)'
   54 |           return std::__invoke(__comp,
      |                  ~~~~~~~~~~~~~^~~~~~~~
   55 |                                std::__invoke(__proj, std::forward<_TL>(__lhs)),
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   56 |                                std::__invoke(__proj, std::forward<_TR>(__rhs)));
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
Run Code Online (Sandbox Code Playgroud)

在线演示: https: //gcc.godbolt.org/z/47xrzM6ch

是否只是因为实现还不够成熟,或者zipview inC++23无法帮助对两个数组进行排序?

Ted*_*gmo 9

至少 libc++ (llvm) 的 trunk 版本支持这一点:

std::ranges::sort(std::views::zip(x, y), [](auto&& a, auto&& b) {
    return std::tie(std::get<0>(a), std::get<1>(a)) < 
           std::tie(std::get<0>(b), std::get<1>(b));
});
Run Code Online (Sandbox Code Playgroud)

演示

如果您使用三个范围而不是两个范围,则无需提供用户定义的比较器函数即可工作:

auto x = std::array{ 3,   2,   4,   1 };
auto y = std::array{'A', 'B', 'C', 'D'};
auto z = std::array{"Z", "Y", "X", "W"};

std::ranges::sort(std::views::zip(x, y, z));
Run Code Online (Sandbox Code Playgroud)

演示

我假设压缩两个范围的版本在完全实现时不需要用户定义的比较器函数。