如何在C++23中对两个容器的enumerated zip进行遍历?
enumerate(zip(A,B))的遍历 想要在C++23里实现和Python中enumerate(zip(A,B))一样的遍历效果——同时获取索引以及两个容器的对应元素。Python里的实现很直观:
A = [10, 20, 30] B = [40, 50, 60] for (i, (a, b)) in enumerate(zip(A, B)): print(i, a, b)
这段代码会依次输出索引i和A、B中对应的元素。
虽然C++23的<ranges>库提供了views::enumerate和views::zip这两个等效视图,但直接嵌套使用时会出现编译错误:
#include <vector> #include <ranges> #include <iostream> using namespace std; int main() { auto A = vector {10, 20, 30}; auto B = vector {40, 50, 60}; // 编译失败的写法 for (auto [i, [a, b]]: views::enumerate(views::zip(A, B))) cout << i << " " << a << " " << b << "\n"; }
编译错误信息包括:
Type 'std::ranges::enumerate_view<...>::_Iterator::__reference_type' (aka 'tuple<long, std::pair<int &, int &>>') decomposes into 2 elements, but only 1 name was provided
Expected identifier
错误原因
问题出在结构化绑定的语法上。views::enumerate返回的每个元素是一个tuple,其中第一个元素是索引,第二个元素是views::zip生成的pair<int&, int&>。C++不支持直接用[i, [a, b]]这种嵌套方括号的结构化绑定写法,方括号在这里会被解析成其他语法,导致编译器无法正确识别绑定的变量名。
解决方案
方法1:拆分结构化绑定
先把enumerate返回的tuple拆成索引i和zip生成的pair,再对pair做二次结构化绑定:
#include <vector> #include <ranges> #include <iostream> using namespace std; int main() { auto A = vector {10, 20, 30}; auto B = vector {40, 50, 60}; for (auto [i, ab_pair]: views::enumerate(views::zip(A, B))) { auto [a, b] = ab_pair; cout << i << " " << a << " " << b << "\n"; } }
方法2:使用圆括号调整绑定结构
C++允许用圆括号来表示嵌套的结构化绑定,把zip返回的pair的绑定用圆括号包裹,替换原来的方括号:
#include <vector> #include <ranges> #include <iostream> using namespace std; int main() { auto A = vector {10, 20, 30}; auto B = vector {40, 50, 60}; // 正确的写法:用圆括号代替方括号 for (auto [i, (a, b)]: views::enumerate(views::zip(A, B))) cout << i << " " << a << " " << b << "\n"; }
运行结果
两种写法都能正常编译运行,输出结果和Python代码一致:
0 10 40 1 20 50 2 30 60
内容的提问来源于stack exchange,提问作者Dan Oak

