Skip to main content
Version: 1.0

ranges

std::ranges 是 C++20 的重磅特性——它重新定义了 STL 算法的调用方式:不再传 begin()end() 迭代器对,而是直接传容器;算法可以通过 | 管道符串联,读写顺序从左到右。

头文件与核心概念

#include <algorithm> // 原有算法获得 ranges 版本
#include <ranges> // 视图适配器(filter, transform 等)

核心变化:

// C++17 风格:begin/end 对
std::sort(vec.begin(), vec.end());
auto it = std::find_if(vec.begin(), vec.end(), pred);

// C++20 ranges 风格:直传容器
std::ranges::sort(vec);
auto it = std::ranges::find_if(vec, pred);

管道式组合(最核心的变革)

视图(views)通过 | 串联,形成惰性求值的管道:

#include <iostream>
#include <ranges>
#include <vector>

int main() {
namespace views = std::views;

std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

auto result = v
| views::filter([](int x) { return x % 2 == 0; }) // 取偶数
| views::transform([](int x) { return x * x; }) // 平方
| views::take(3); // 取前 3 个

for (int x : result) {
std::cout << x << ' '; // 4 16 36
}

return 0;
}

管道从左到右读:从 v 出发 → 过滤偶数 → 平方 → 取前三个。整个过程惰性求值——元素只在迭代时才被计算。

常用视图

视图作用
views::filter(pred)过滤
views::transform(fn)映射转换
views::take(n)取前 n 个
views::drop(n)跳过前 n 个
views::reverse逆序
views::keys / views::valuesmap 的键/值视图
views::iota(start, end)整数序列
views::split(delim)按分隔符切分
views::join展平嵌套
views::common转为 common_range(兼容旧代码)

投影(Projection)

ranges 算法支持投影参数,在对元素操作前先做一次转换:

#include <algorithm>
#include <ranges>
#include <vector>

struct User {
std::string name;
int age;
};

int main() {
std::vector<User> users = {{"Bob", 25}, {"Alice", 30}, {"Cathy", 20}};

// 按 age 排序,投影告诉 sort 从每个元素提取 age
std::ranges::sort(users, {}, &User::age);
// users 现在按 age 升序排列

return 0;
}

{} 是默认比较器,&User::age 是投影——这种模式在 ranges 算法中广泛使用。

使用注意

  1. 视图是惰性的,修改源容器后视图反映最新数据(filter 等除外)。
  2. filter_view 不可随机访问,传回旧算法时会受限。
  3. 管道链不要写得太长——和 LINQ 一样,适度即可。
  4. ranges:: 版本的算法在 <algorithm> 头文件,views::<ranges> 头文件。

小结

std::ranges 是 C++20 对 STL 算法的重新发明。管道语法让数据流处理更可读,投影让自定义比较更简洁。在 C++20 项目中,优先使用 std::ranges:: 版本的算法。