如何仅通过std::ranges::views迭代器判断其是否为尾迭代器?
解决方案
当然可以不用显式存储vals | rv::slide(2)这个视图,有两种简单方法能满足你的需求:
方法一:临时构造视图并直接取尾迭代器
你可以在判断条件里直接构造同一个slide视图,然后调用它的end()来和adj_dup比较:
namespace r = std::ranges; namespace rv = std::ranges::views; std::optional<int> find_first_adjacent_duplicate(std::span<int> vals) { auto adj_dup = r::find_if(vals | rv::slide(2), [](auto&& r) {return r[0] == r[1]; }); if (adj_dup != (vals | rv::slide(2)).end()) { return (*adj_dup)[0]; } else { return {}; } }
不用担心临时构造的开销——slide视图是轻量级的适配器,不会复制原数据,而且基于同一个源范围构造的同类型视图,其迭代器是可以合法比较相等性的,符合C++20范围标准的要求。
方法二:用std::ranges::end函数获取尾迭代器
另一种写法是用r::end函数,直接传入临时构造的视图来获取尾迭代器:
namespace r = std::ranges; namespace rv = std::ranges::views; std::optional<int> find_first_adjacent_duplicate(std::span<int> vals) { auto adj_dup = r::find_if(vals | rv::slide(2), [](auto&& r) {return r[0] == r[1]; }); if (adj_dup != r::end(vals | rv::slide(2))) { return (*adj_dup)[0]; } else { return {}; } }
额外的简洁写法(仍需保存视图,但更紧凑)
如果想让代码更短,还可以利用三元表达式直接返回std::optional:
namespace r = std::ranges; namespace rv = std::ranges::views; std::optional<int> find_first_adjacent_duplicate(std::span<int> vals) { auto pairs = vals | rv::slide(2); auto it = r::find_if(pairs, [](auto&& r) {return r[0] == r[1]; }); return it != r::end(pairs) ? std::optional{(*it)[0]} : std::nullopt; }
不过这个写法还是保留了pairs变量,主要是优化返回逻辑的简洁性。
内容的提问来源于stack exchange,提问作者jwezorek
相关产品推荐
相关产品推荐

