如何在C++中创建保留随机访问特性的join view?
如何合并随机访问子范围并保留随机访问特性(排除vector特定元素的随机访问视图)
原代码中views::join拼接两个随机访问子范围后,生成的视图仅支持forward迭代器,无法直接使用+1这类随机访问操作——因为迭代器无法通过偏移量O(1)判断目标元素属于哪个子范围,必须遍历跳转,所以会报错。
要实现排除特定元素且支持随机访问的vector视图,核心思路是利用原vector的连续存储特性,通过索引映射构造随机访问视图,具体分两种场景:
场景1:排除单个元素
直接计算视图索引与原vector索引的映射关系,用views::iota生成连续索引,再通过views::transform映射到原vector的对应元素:
#include <vector> #include <ranges> #include <iostream> int main() { std::vector<std::string> v0 = {"word","good","best","good"}; const size_t exclude_idx = 1; // 要排除的元素在原vector中的位置 // 构造支持随机访问的过滤视图 auto filtered_view = std::views::iota(0u, v0.size() - 1) | std::views::transform([&](size_t j) { // 视图的第j个元素:若j在排除位置前,直接取原索引j;否则取原索引j+1 return v0[j + (j >= exclude_idx ? 1 : 0)]; }); // 验证随机访问 auto w1 = filtered_view.begin() + 1; std::cout << *w1 << std::endl; // 输出 "best" return 0; }
场景2:排除多个不连续元素
先预先生成需要保留的元素的原索引列表,再通过索引映射构造视图:
#include <vector> #include <ranges> #include <iostream> int main() { std::vector<std::string> v0 = {"word","good","best","good","test"}; const std::vector<size_t> keep_indices = {0, 2, 4}; // 保留这些索引的元素,排除1、3 // 构造支持随机访问的过滤视图 auto filtered_view = std::views::iota(0u, keep_indices.size()) | std::views::transform([&](size_t j) { return v0[keep_indices[j]]; }); // 验证随机访问 auto w2 = filtered_view.begin() + 2; std::cout << *w2 << std::endl; // 输出 "test" return 0; }
关键说明
- 这两种方案的核心是O(1)的索引映射:原vector是随机访问容器,通过索引计算可以直接定位元素,因此视图的迭代器支持
+、-、[]等随机访问操作。 views::join无法满足需求的原因:它拼接的是两个不连续的子范围,迭代器无法通过偏移量直接判断目标元素所属的子范围,只能逐个遍历,因此仅支持forward迭代器,不具备随机访问能力。
内容的提问来源于stack exchange,提问作者ephemerr
相关产品推荐
相关产品推荐

