现代 C++ 实战(17):C++23 新特性
C++20 上了 Concepts、协程、Ranges;C++23 继续「还债」:std::expected 补错误处理、std::print 补输出、deducing this 补成员函数模板、std::generator 补协程生成器——不必等 C++26 也能用上不少干货。
这一篇对应 demo:ref/cpp_demo/basics/cpp23_features/(含条件编译,按编译器能力启用特性)。
这是「现代 C++ 实战」系列的第 17 篇。建议先读 第 16 篇:GoogleTest 与 第 08 篇:错误处理。
一、C++23 概览
| 特性 | 解决什么 |
|---|---|
std::expected<T, E> |
成功值 + 错误原因,替代部分异常/错误码 |
| deducing this | 一份成员函数覆盖 const/非 const |
std::print / println |
类型安全格式化输出 |
std::generator |
标准协程生成器(惰性序列) |
if consteval |
constexpr 函数里区分编译期/运行期 |
std::mdspan、多维 [] |
多维数组非拥有视图 |
| Ranges 增强 | zip、enumerate、chunk… |
42uz |
size_t 字面量,消除符号警告 |
编译器支持参差不齐——demo 用 __has_include 与特性宏做条件编译;GCC 13+、Clang 17+ 起步,部分特性需 GCC 14 / Clang 18。
二、std::expected:Result 的 C++ 版
类似 Rust 的 Result<T, E>:要么有值 T,要么有错误 E。
1 |
|
| 方式 | 缺点 |
|---|---|
| 异常 | 控制流隐式、部分场景开销大 |
| 错误码 | 易忽略返回值 |
optional |
只知失败,不知原因 |
expected |
值 + 错误类型都明确 |
常用 API:
1 | auto r = parse_int("42"); |
与 第 08 篇 对照:expected 适合可预期的失败(解析、文件打开);异常仍适合真正异常路径。
三、deducing this:显式 this 参数
以前 const / 非 const 各写一份:
1 | int& at(size_t i) { return data[i]; } |
C++23 deducing this 合并为一份:
1 | template <typename Self> |
编译器根据 self 是 T&、const T&、T&& 推导 const 性与值类别。还可用于链式调用、递归 lambda:
1 | auto factorial = [](this auto&& self, int n) -> int { |
需 __cpp_explicit_this_parameter >= 202110L(GCC 14+、Clang 18+ 较完整)。
四、std::print / std::println
终于不必 cout << 链式拼接:
1 |
|
基于 std::format(第 09 篇),类型安全、可本地化。头文件 <print>,GCC 14+ / Clang 18+ 库支持较新。
五、std::generator:协程生成器
C++20 有协程,但缺标准「生成器」类型;C++23 补上:
1 |
|
惰性:按需 co_yield,适合大序列、管道式处理。编译器与 <generator> 头文件支持仍在完善中。
六、if consteval:编译期 vs 运行期
在 constexpr 函数里同一签名、两套实现:
1 | constexpr int heavy_or_simple(int n) { |
if consteval 分支在编译期求值时必须可走 constexpr 路径;比 if (std::is_constant_evaluated()) 语义更清晰。
七、std::mdspan 与多维 []
多维数组的非拥有视图(不拷贝数据):
1 |
|
配合 std::extents 描述形状,适合矩阵、图像块、科学计算。替代手写 buf[i * cols + j]。
八、其他实用改动
| 特性 | 示例 / 说明 |
|---|---|
42uz |
size_t 字面量,for (auto i = 0uz; i < v.size(); ++i) |
std::to_underlying |
std::to_underlying(Color::Red) 取 enum 底层值 |
std::flat_map / flat_set |
连续内存有序关联容器,缓存友好 |
| Ranges | views::zip、enumerate、chunk、slide…(详见 第 10 篇) |
1 | // enumerate — 类似 Python |
九、demo 运行与编译器要求
1 | cd ref/cpp_demo/basics/cpp23_features |
程序末尾会打印当前编译器对 expected、print、deducing this、generator、uz 等的 ✅/❌ 支持情况。
| 特性 | 大致要求 |
|---|---|
std::expected |
GCC 13+、Clang 17+ |
std::print、deducing this |
GCC 14+、Clang 18+ |
std::generator |
较新 libc++ / libstdc++ |
| 全量 C++23 | -std=c++23,__cplusplus == 202302L |
策略:新代码用 expected + print;旧编译器用 #if __has_include(<expected>) 回退到 optional 或错误码。
十、小结
| 特性 | 一句话 |
|---|---|
| expected | 值或错误,可链式 transform |
| deducing this | 一份成员函数,const/非 const 通吃 |
| format 风格的标准输出 | |
| generator | 协程惰性序列 |
| if consteval | constexpr 内外分支 |
| mdspan | 多维数组视图 |
现代 C++ 实战系列第 17 篇完。下一篇进入第三季:排序算法与 std::sort。
系列导航
| 篇号 | 标题 | 状态 |
|---|---|---|
| 16 | GoogleTest 单元测试 | ✅ |
| 17 | C++23 新特性(本篇) | ✅ |
| 18 | 排序算法与 std::sort | 下一篇 |
完整大纲见工作区 docs/CPP_SERIES_OUTLINE.md。










