std::views::chunk_by按相邻元素谓词结果变化切分,非固定大小分组;要求forward_range(如vector)、谓词须二元且不可捕获非常量状态,与chunk功能无关。

std::views::chunk_by 不是按固定大小切块,它只响应相邻元素间谓词结果的“变化点”——传 std::equal_to{} 或硬写 == 也得不到等长分组。
std::views::chunk_by 的触发条件:仅当相邻元素间谓词返回值翻转时才切分
它不是“每 N 个一组”,而是“只要谓词对 (a,b) 和 (b,c) 返回不同结果,就在 b 后切一刀”。典型场景是连续相同值分组(类似 Python 的 itertools.groupby),但谓词可以任意定义。
- 输入序列
{1,1,2,2,2,3,1}配合谓词std::equal_to{}→ 分成{1,1}、{2,2,2}、{3}、{1}(注意最后两个单元素块) - 谓词写成
[&](int a, int b) { return a % 2 == b % 2; }→ 按奇偶连续性分组:{1,1}、{2,2,2}、{3,1} - 若整个序列满足谓词恒为
true(如全相同元素),则输出只有 1 个块;若恒为false(如严格递增),则每个元素都是独立块
std::views::chunk_by 要求输入是 forward_range,且不能用 std::list
它需要能多次遍历同一位置(比如回退一个元素做比较),所以 std::list 和 std::forward_list 不满足约束,编译直接失败。常见可用类型只有 std::vector、std::array、原生数组、std::string 等。
- 错误示例:
std::list→ 编译报错,提示l = {1,2,2,3}; auto v = l | std::views::chunk_by(std::equal_to{}); forward_range不满足 - 正确替代:先转成
std::vector,或改用支持前向迭代的容器 - 性能影响:每次取下一个块时,内部需推进迭代器并缓存上一个值,有常数级额外开销,但不复制元素
std::views::chunk_by 的谓词必须是二元的,且不能捕获可变状态
签名强制要求接受两个同类型参数(T, T),返回 bool。闭包若捕获局部变量(尤其是非 const 变量),会导致视图对象不可复制,进而破坏管道组合语义。
- 安全写法:
[=](int a, int b) { return a (仅读捕获,且为 const) - 危险写法:
[&counter](int a, int b) { return ++counter & 1; }→chunk_by视图不可复制,后续接| std::views::transform等会编译失败 - 调试提示:若遇到 “
use of deleted function” 或 “copy constructor is implicitly deleted”,大概率是谓词捕获了引用或非常量对象
chunk_by 和 chunk 完全不兼容,别混用名字或预期
名字像,行为毫无关系:std::views::chunk(3) 是按数字 3 切,std::views::chunk_by(...) 是按逻辑变化切。强行把 chunk_by 当 chunk 用,唯一结果就是逻辑错乱。
- 想实现“每 3 个一组”?只能用
std::views::chunk(3),且注意它要求random_access_range(std::list仍不行) - 想合并连续偶数段?用
chunk_by配[=](int a, int b) { return (a%2==0) == (b%2==0); } - 最容易忽略的一点:chunk_by 的块数量取决于数据分布,而 chunk 的块数量由长度和步长决定——前者不可预测,后者完全可控
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











