C++20 是 C++ 语言家族的一次重大升级,新增了许多功能来提高语言的表达力、简化代码以及提升性能。本文将重点介绍三大新特性:范围视图(Ranges Views)、协程(Coroutines)以及概念(Concepts),并给出每个特性的基本用法与常见场景。
1. 范围视图(Ranges Views)
1.1 背景
传统的 STL 迭代器模式需要手动编写循环或使用 std::transform、std::accumulate 等算法,代码冗长且不易阅读。C++20 的 std::ranges 提供了一套函数式的视图(view)和适配器(adapter),可以链式组合,形成不可变的“惰性序列”。
1.2 基本语法
#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector <int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto even = std::views::filter([](int n){ return n % 2 == 0; });
auto squared = std::views::transform([](int n){ return n * n; });
for (int n : vec | even | squared) {
std::cout << n << ' '; // 4 16 36 64 100
}
}
1.3 常用视图
| 视图 | 作用 | 示例 |
|---|---|---|
std::views::filter |
根据谓词过滤元素 | vec | std::views::filter(is_prime) |
std::views::transform |
对每个元素应用函数 | vec | std::views::transform([](auto x){ return x * 2; }) |
std::views::take |
截取前 N 个元素 | vec | std::views::take(5) |
std::views::drop |
跳过前 N 个元素 | vec | std::views::drop(3) |
std::views::reverse |
逆序 | vec | std::views::reverse |
2. 协程(Coroutines)
2.1 背景
协程使得异步编程变得更直观、可读。传统的回调或状态机模式容易导致“回调地狱”。C++20 的协程提供了 co_await、co_yield、co_return 关键字,支持暂停与恢复。
2.2 简单生成器
#include <coroutine>
#include <iostream>
struct Generator {
struct promise_type;
using handle_type = std::coroutine_handle <promise_type>;
struct promise_type {
int value_;
Generator get_return_object() {
return Generator{handle_type::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(int v) {
value_ = v;
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
handle_type coro_;
Generator(handle_type h) : coro_(h) {}
~Generator() { coro_.destroy(); }
bool next() { return coro_.resume(); }
int value() const { return coro_.promise().value_; }
};
Generator range(int start, int end) {
for (int i = start; i <= end; ++i)
co_yield i;
}
int main() {
auto gen = range(1, 5);
while (gen.next()) {
std::cout << gen.value() << ' '; // 1 2 3 4 5
}
}
2.3 应用场景
- 异步 I/O(如网络请求、文件读取)
- 数据流(可按需产生)
- 迭代器的简化实现
3. 概念(Concepts)
3.1 背景
模板编程经常出现“模板雾”问题:错误信息难以理解、未满足约束导致编译报错。概念为模板参数添加了语义层,能够在编译时对类型进行检查,并给出友好的错误提示。
3.2 定义与使用
#include <concepts>
#include <iostream>
template <typename T>
concept Incrementable = requires(T x) {
{ ++x } -> std::same_as<T&>;
{ x++ } -> std::same_as <T>;
};
template <Incrementable T>
void increment(T& t) {
++t;
}
int main() {
int a = 5;
increment(a); // 6
}
3.3 典型概念
| 名称 | 说明 |
|---|---|
std::integral |
整数类型 |
std::floating_point |
浮点类型 |
std::ranges::range |
范围类型 |
| `std::same_as | |
| 与T` 同类型 |
|
| `std::derived_from | |
| 继承自B` |
4. 小结
- 范围视图:让序列处理更加声明式,减少样板代码。
- 协程:提供简洁的异步编程模型,天然支持惰性求值。
- 概念:提升模板代码的可读性与错误可诊断性。
这三大新特性共同推动 C++ 向更安全、更高效、更易用的方向发展。掌握它们后,你将能写出更现代、更符合现代软件工程要求的 C++ 代码。祝你编码愉快!