在Range V3中用split_when替代chunk_by后如何获取块大小?
如何获取C++ ranges split_when生成块的大小?
你用split_when替换chunk_by + filter后,没法直接获取块大小的原因是:split_when生成的每个子范围属于输入范围(input range),这类范围不强制支持size()成员函数,也不能直接用std::ranges::size计算长度;而chunk_by返回的子范围如果原容器是随机访问类型(比如std::vector),通常会保留随机访问特性,所以能直接获取大小。
针对这个问题,有几种可行的解决方式:
1. 用std::ranges::distance计算大小
std::ranges::distance可以遍历输入范围并返回元素数量,但要注意:输入范围的迭代器是单遍的,调用distance后,块的迭代器会走到末尾,后续如果还要访问块内元素需要重新生成这个块。
#include <ranges> #include <iterator> // ... auto v2 = a_container | ::ranges::views::split_when(lambda_split); for (auto &e : v2) { std::size_t chunk_size = std::ranges::distance(e); // 使用chunk_size,此时e的迭代器已耗尽,无法再访问元素 }
2. 将块转换为随机访问容器(如std::vector)
如果性能开销在可接受范围内,可以把每个块拷贝到std::vector这类支持随机访问的容器中,这样就能直接用size()获取长度,同时也能正常访问块内任意元素。
#include <ranges> #include <vector> // ... auto v2 = a_container | ::ranges::views::split_when(lambda_split) | ::ranges::views::transform([](auto chunk) { return std::vector(chunk.begin(), chunk.end()); }); for (auto &e : v2) { std::size_t chunk_size = e.size(); // 可正常访问e.front()、e.back()或任意元素 }
3. 遍历块时手动计数
如果需要在获取大小的同时处理元素,可以直接遍历块并计数,这样既不需要额外拷贝,也不会提前耗尽迭代器。
#include <ranges> // ... auto v2 = a_container | ::ranges::views::split_when(lambda_split); for (auto &e : v2) { std::size_t chunk_size = 0; for (auto &elem : e) { ++chunk_size; // 同时可以对elem进行处理 } // 使用chunk_size }
内容的提问来源于stack exchange,提问作者Kroma
相关产品推荐
相关产品推荐

