如何使用Range-v3的join函数实现两个deque容器的合并视图
核心问题说明
你的原有写法存在两个核心错误:
- 你调用的
ranges::actions::join属于动作(Action)范畴,作用是直接修改原容器内容,不会生成独立的合并视图,不符合你不改动原容器、仅创建视图的需求。 join视图本身的语义是拍平嵌套范围(比如std::array<std::deque<data_t>, 2>这种两层结构),不能直接接收两个独立的平级deque作为输入。
正确实现方案
方案1:使用join视图实现
要使用join完成两个deque的合并,需要先把两个deque打包为一个外层的嵌套范围,再用join拍平得到合并视图:
#include <range/v3/all.hpp> #include <deque> #include <iostream> #include <array> struct data_t { int data; int some_other_data; }; auto main() -> int { using namespace ranges; auto v1 = std::deque<data_t>() = { {1,1}, {2,2}, {3,3}, {4,4}, {5,5} }; auto v2 = std::deque<data_t>() = { {6,6}, {7,7}, {8,8}, {9,9}, {10,10} }; // 先将两个deque打包为数组(外层嵌套范围),再用join拍平得到视图 auto vv = views::all(std::array{std::ref(v1), std::ref(v2)}) | views::join; for(auto const& v : vv) { std::cout << v.data << ", " << '\n'; } return 0; }
方案2:使用更适配的concat视图(推荐)
合并多个平级范围的场景下,直接使用views::concat更简洁,不需要额外打包嵌套结构:
#include <range/v3/all.hpp> #include <deque> #include <iostream> struct data_t { int data; int some_other_data; }; auto main() -> int { using namespace ranges; auto v1 = std::deque<data_t>() = { {1,1}, {2,2}, {3,3}, {4,4}, {5,5} }; auto v2 = std::deque<data_t>() = { {6,6}, {7,7}, {8,8}, {9,9}, {10,10} }; // 直接拼接两个deque生成合并视图,无元素拷贝 auto vv = views::concat(v1, v2); for(auto const& v : vv) { std::cout << v.data << ", " << '\n'; } return 0; }
补充说明
- 上述两种方案生成的都是轻量视图,不会拷贝原deque中的元素,修改原容器内的元素会同步反映到视图中。
- 如果你确实需要修改原容器、将v2的内容合并到v1中,可以直接用动作接口实现:
ranges::actions::push_back(v1, v2); // 直接把v2元素追加到v1末尾 - 如果需要生成新的独立deque容器,可以把视图直接转成对应容器:
auto merged_deque = views::concat(v1, v2) | ranges::to<std::deque<data_t>>();
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

