为何使用std::ranges::find查找std::views::zip的代码无法编译?
C++23中std::views::zip配合范围查找的编译错误解决
问题重现
原始代码(编译失败)
#include <ranges> #include <iostream> #include <vector> int main() { std::vector<int> v1{1,2,3,4}; std::vector<int> v2{2,4,6,8}; auto z = std::views::zip(v1, v2); if(std::ranges::find(z, {2, 4}) != z.end()) { std::cout << "(2,4) in zip\n"; } return 0; }
报错信息
zip.cpp:11:25: error: no match for call to ‘(const std::ranges::__find_fn) (std::ranges::zip_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&, <brace-enclosed initializer list>)’
修改后的代码(仍编译失败)
#include <ranges> #include <iostream> #include <vector> int main() { std::vector<int> v1{1,2,3,4}; std::vector<int> v2{2,4,6,8}; auto z = std::views::zip(v1, v2); if(std::ranges::find_if(z, [](auto p){return p == std::make_pair(2, 4);}) != z.end()) { std::cout << "(2,4) in zip\n"; } return 0; }
报错信息
zip.cpp:10:52: error: no match for ‘operator==’ (operand types are ‘std::pair<int&, int&>’ and ‘std::pair<int, int>’)
错误原因分析
- 初始化列表推导失败:
std::ranges::find无法直接接收初始化列表{2,4}作为查找值——编译器无法从无类型的初始化列表推导匹配的目标类型,导致模板参数推导失败。 - 引用pair与值pair无法直接比较:
std::views::zip返回的视图元素是std::pair<int&, int&>(对原始vector元素的引用),而std::make_pair(2,4)生成的是std::pair<int, int>(值类型),标准库未提供这两种类型的operator==重载,因此比较操作无法通过编译。
可行解决方案
方案1:直接比较元素值(最简洁)
跳过pair对象的比较,直接在lambda中检查两个元素的具体值,完全规避类型不匹配问题:
#include <ranges> #include <iostream> #include <vector> int main() { std::vector<int> v1{1,2,3,4}; std::vector<int> v2{2,4,6,8}; auto z = std::views::zip(v1, v2); if(std::ranges::find_if(z, [](auto&& p){ return std::get<0>(p) == 2 && std::get<1>(p) == 4; }) != z.end()) { std::cout << "(2,4) in zip\n"; } return 0; }
方案2:将引用pair转换为值pair后比较
在lambda中把引用类型的pair转换为值类型,再和目标值pair比较:
#include <ranges> #include <iostream> #include <vector> #include <utility> int main() { std::vector<int> v1{1,2,3,4}; std::vector<int> v2{2,4,6,8}; auto z = std::views::zip(v1, v2); if(std::ranges::find_if(z, [](auto p){ return std::pair<int, int>(p) == std::make_pair(2, 4); }) != z.end()) { std::cout << "(2,4) in zip\n"; } return 0; }
方案3:使用std::ranges::find配合投影
通过投影将引用pair转换为值pair,让std::ranges::find可以正确匹配查找值:
#include <ranges> #include <iostream> #include <vector> #include <utility> int main() { std::vector<int> v1{1,2,3,4}; std::vector<int> v2{2,4,6,8}; auto z = std::views::zip(v1, v2); if(std::ranges::find(z, std::make_pair(2,4), [](auto&& p){ return std::pair<int, int>(std::get<0>(p), std::get<1>(p)); }) != z.end()) { std::cout << "(2,4) in zip\n"; } return 0; }
内容的提问来源于stack exchange,提问作者Alberto Santini
相关产品推荐
相关产品推荐

