首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用C++23 zip视图对两个数组进行排序

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

Stack Overflow用户
提问于 2022-11-27 08:15:30
回答 2查看 159关注 0票数 6

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

现在可以使用范围-v3库解决此任务:

代码语言:javascript
复制
#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'}
}

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

在C++23中,视图出现了,我的期望是同一程序只能使用标准库编写:

代码语言:javascript
复制
#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 ) );
}

不幸的是,它会导致长时间的编译错误。例如在GCC中:

代码语言:javascript
复制
...
/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)));
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...

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

这仅仅是因为实现还不够成熟,还是C++23中的C++23视图无助于对两个数组进行排序?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-27 09:02:35

至少libc++ (llvm)的主干版本支持这样的功能:

代码语言:javascript
复制
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));
});

演示

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

代码语言:javascript
复制
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));

演示

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

票数 7
EN

Stack Overflow用户

发布于 2022-11-27 14:00:05

除了传递自定义比较器(如其他答案)外,还可以传递自定义投影函数,将pair映射到tuple

代码语言:javascript
复制
ranges::sort(views::zip(x, y), {}, [](auto p) { return std::tuple(p); });

这将将pair<int&, char&>转换为tuple<int&, char&>,使ranges::less正常工作。

演示

但是,由于C++23将value_type of zip_view的迭代器改为tuple (在此之前,当范围数为2时,zip_view将特别使用pair作为value_type ),所以代码在C++23中格式良好。

您唯一需要做的就是等待编译器实现P2165

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74588501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档