You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C++23 zip_view排序两个数组遇编译错误,原因何在?

同时排序两个数组:C++23 zip_view 为何无法工作?

有一个经典任务:将两个数组按同索引元素构成的虚拟对进行排序,这类需求早在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 ) );
   // 排序后 x = {1,2,3,4}, y={'D','B','A','C'}
}

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 ) );
}

但编译时会出现类似这样的错误(以GCC为例):

/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)));
      |                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

问题根源

这不是编译器实现不成熟,而是C++23标准对zip_view的设计导致的:

  • std::views::zip(x,y)返回的zip_view,其元素类型是tuple<int&, char&>(引用类型的元组)。
  • std::ranges::sort在排序过程中,需要临时存储元素(比如交换、分区操作时),此时会生成值类型的元组tuple<int, char>。
  • 默认比较器std::ranges::less无法处理引用元组和值元组之间的比较——这两种类型不匹配,没有对应的operator<重载支持。

而range-v3的zip_view在设计时做了特殊处理,确保比较逻辑能兼容引用和值的混合场景,所以可以直接调用sort。

解决方法

你可以自定义一个比较器,显式处理两种类型的比较:

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

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),
       [](const auto& lhs, const auto& rhs) {
           return std::tie(lhs) < std::tie(rhs);
       });
}

std::tie会把任意tuple-like对象转换成引用元组,无论传入的是引用元组还是值元组,都会统一成引用类型的比较逻辑,从而解决类型不匹配的问题。

内容的提问来源于stack exchange,提问作者Fedor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:20:29