C++标准库在C++20引入了Ranges特性,后续版本又不断补充了新的范围适配器,std::views::chunk_by就是其中用于按谓词逻辑切分序列的重要工具,它可以将一个连续的输入序列,按照相邻元素是否满足指定谓词条件,拆分成多个相邻的子范围视图。

std::views::chunk_by 基本语法
std::views::chunk_by是一个范围适配器,它的基本调用形式如下:
#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {1, 2, 3, 5, 6, 7, 9, 10};
// 按相邻元素差值是否大于1切分序列
auto chunk_view = nums | std::views::chunk_by([](int a, int b) {
return b - a <= 1;
});
// 遍历切分后的每个子范围
for (auto sub_range : chunk_view) {
for (auto val : sub_range) {
std::cout << val << " ";
}
std::cout << std::endl;
}
return 0;
}
上述代码中,谓词函数接收两个相邻的元素a和b,当返回true时,说明这两个元素属于同一个分组,返回false时则会在这两个元素之间切分,生成新的子范围。
工作原理说明
std::views::chunk_by的工作逻辑是遍历输入序列,依次比较相邻的两个元素:
- 如果相邻元素满足谓词条件,就将这两个元素归到同一个子范围中
- 如果相邻元素不满足谓词条件,就在这两个元素之间做切分,前一个子范围结束,后一个子范围从当前元素开始
- 最终输出的视图由多个相邻的子范围组成,每个子范围都是输入序列的连续片段
需要注意的是,谓词函数只会在相邻元素之间调用,不会跨元素比较,因此切分逻辑是基于相邻元素的连续关系判断的。
常见使用场景
连续数值分组
比如将一组整数中连续递增且差值为1的元素分为一组,前面给出的示例就是这种场景,最终输出结果为:
1 2 3 5 6 7 9 10
按元素属性分组
对于自定义类型的序列,也可以根据相邻元素的属性判断是否分组,比如按相邻学生的成绩是否在同一分数段分组:
#include <ranges>
#include <vector>
#include <string>
#include <iostream>
struct Student {
std::string name;
int score;
};
int main() {
std::vector<Student> students = {
{"张三", 85}, {"李四", 88}, {"王五", 92}, {"赵六", 75}, {"钱七", 78}
};
// 相邻学生成绩差值不超过5分为一组
auto score_groups = students | std::views::chunk_by([](const Student& s1, const Student& s2) {
return std::abs(s1.score - s2.score) <= 5;
});
for (auto group : score_groups) {
for (const auto& stu : group) {
std::cout << stu.name << ":" << stu.score << " ";
}
std::cout << std::endl;
}
return 0;
}
使用注意事项
- std::views::chunk_by是C++23才正式纳入标准库的特性,使用前需要确认编译器是否支持对应版本,比如GCC 13及以上、Clang 16及以上版本才支持该特性
- 输入序列必须是至少支持前向迭代的范围,因为需要遍历相邻元素做判断
- 谓词函数需要满足严格弱序的要求,否则切分结果可能不符合预期
- std::views::chunk_by返回的是视图,不会拷贝原始序列的元素,因此原始序列的生命周期需要长于视图的使用周期
和其他切分适配器的区别
和std::views::chunk不同,std::views::chunk_by不是按固定大小切分序列,而是按相邻元素的谓词判断动态切分;和std::views::split也不同,split是按指定的分隔元素切分,而chunk_by是按相邻元素的关系切分,不需要指定固定的分隔值。
| 适配器 | 切分依据 | 切分粒度 |
|---|---|---|
| std::views::chunk | 固定大小 | 每个子范围元素数量固定 |
| std::views::split | 指定分隔元素 | 分隔元素不会被包含在子范围中 |
| std::views::chunk_by | 相邻元素谓词判断 | 子范围大小由序列内容和谓词共同决定 |
C++std::views::chunk_byRange谓词逻辑序列切分修改时间:2026-07-22 23:54:33