C++20中Views管道与ranges adjacent_find迭代器无效错误修复
问题原因分析
std::ranges::adjacent_find(带自定义二元谓词的重载)要求输入范围满足**forward_range**概念——即迭代器至少是forward iterator,支持多次遍历、保存迭代器后复用。- 你的代码中,第一个
std::views::transform(get_vectors)按值返回std::vector<int>,导致transform_view生成的元素是临时vector对象(右值)。join_view处理这种产出右值范围的视图时,生成的迭代器属于input iterator类别(临时对象会被销毁,无法安全保存迭代器并重新访问元素)。后续的transform视图不会提升迭代器类别,最终all_ints是input range,不满足adjacent_find的要求,触发编译错误。
修复方案
方案1:移除冗余的transform视图
你的第一个transform(get_vectors)完全多余——vectors_of_ints本身就是std::vector<std::vector<int>>,直接通过std::views::join就能展开所有子vector的元素:
#include <algorithm> #include <ranges> #include <vector> auto main() -> int { std::vector<std::vector<int>> vectors_of_ints { {1, 2, 3}, {4, 5, 6} }; // 直接展开嵌套vector,得到所有int的视图 auto all_ints = vectors_of_ints | std::views::join; // 检查是否存在不相等的相邻元素(即不是所有值都相同) auto status = std::ranges::adjacent_find(all_ints, std::not_equal_to{}) != std::ranges::end(all_ints); return status; }
方案2:保留transform时返回引用(针对实际代码有复杂逻辑的场景)
如果实际代码中get_vectors有额外处理逻辑,必须保留transform,那么修改lambda返回子vector的引用,确保transform_view产出左值范围:
auto get_vectors = [](const std::vector<int>& v) -> const std::vector<int>& { // 这里可以添加自定义逻辑 return v; }; // 后续join后的迭代器会提升为forward iterator,满足adjacent_find要求 auto all_ints = vectors_of_ints | std::views::transform(get_vectors) | std::views::join;
额外说明:逻辑澄清
- 你当前的代码逻辑是检查是否存在不相等的相邻元素(即不是所有值都相同),返回
true表示存在差异。 - 如果要检查所有值是否唯一(无重复),仅用
adjacent_find不够,需要先排序再检查:
auto sorted_ints = all_ints | std::views::sort; auto has_duplicates = std::ranges::adjacent_find(sorted_ints) != std::ranges::end(sorted_ints); auto all_unique = !has_duplicates;
内容的提问来源于stack exchange,提问作者masuo
相关产品推荐
相关产品推荐

