现代 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++23 编译,库特性再用条件编译按标准库能力启用)。
这是「现代 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 的 CMake 要求 -std=c++23(GCC 14+ / Clang 18+ / Apple Clang 16+),在此之上再用 __has_include(<expected>) / __has_include(<print>) / __has_include(<generator>) 与 __cpp_explicit_this_parameter 做条件编译,标准库缺哪个就只打印说明。
demo(单文件 cpp23_features.cpp)真正跑代码的是 std::expected、deducing this、uz 字面量三项;if consteval、多维 []、std::to_underlying、Ranges 增强只打印文字说明或伪代码,std::print / std::generator 只做支持检测。下文这几节的代码是通用示意。
二、std::expected:Result 的 C++ 版
类似 Rust 的 Result<T, E>:要么有值 T,要么有错误 E。
1 |
|
(demo 的 parse_int:空串 → EmptyInput,"abc" → InvalidFormat,"9999" → OutOfRange。)
| 方式 | 缺点 |
|---|---|
| 异常 | 控制流隐式、部分场景开销大 |
| 错误码 | 易忽略返回值 |
optional |
只知失败,不知原因 |
expected |
值 + 错误类型都明确 |
常用 API:
1 | auto r = parse_int("42"); |
demo 还有一个 parse_and_sqrt:parse_int(str).transform(...) 把 expected<int, ParseError> 变成 expected<double, ParseError>,错误原样透传。
与 第 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 性与值类别(demo 中 OldStyle / NewStyle 两个 struct 对照)。还可用于链式调用(demo 的 set_first(this auto&& self, int val))、递归 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 | int simd_square(int n); // 运行期优化实现,省略 |
if consteval 分支在编译期求值时必须可走 constexpr 路径;比 if (std::is_constant_evaluated()) 语义更清晰。
七、std::mdspan 与多维 []
多维数组的非拥有视图(不拷贝数据):
1 |
|
配合 std::extents<IndexType, Extents...> 描述形状(第一个模板参数是下标类型),适合矩阵、图像块、科学计算。替代手写 buf[i * cols + j]。<mdspan> 需要较新的标准库(libstdc++ 15 / libc++ 17 起)。
八、其他实用改动
| 特性 | 示例 / 说明 |
|---|---|
42uz |
size_t 字面量,for (auto i = 0uz; i < v.size(); ++i) |
std::to_underlying |
std::to_underlying(Color::Red) 取 enum 底层值(demo 里只留了注释,实际仍用 static_cast<std::underlying_type_t<Color>>) |
std::flat_map / flat_set |
连续内存有序关联容器,缓存友好 |
| Ranges | views::zip、enumerate、chunk、slide…(详见 第 10 篇) |
1 | // enumerate — 类似 Python |
九、demo 运行与编译器要求
1 | cd ref/cpp_demo/basics/cpp23_features |
程序(target cpp23_features)依次调用 demo_expected()、demo_deducing_this()、demo_misc_features()、demo_ranges_enhancements(),最后 demo_feature_summary() 打印当前编译器对 std::expected、std::print、Deducing this、std::generator、size_t literal (uz) 五项的 ✅/❌ 支持情况,以及 __cplusplus 的值。
| 特性 | 大致要求 |
|---|---|
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 |
demo 的 CMakeLists.txt 设置了 CMAKE_CXX_STANDARD 23 + CMAKE_CXX_STANDARD_REQUIRED ON,编译器不支持 C++23 时会直接报错,不再静默回退到 C++20。至少需要 GCC 14+ / Clang 18+ / Apple Clang 16+;系列 Docker 镜像默认的 GCC 15 可以直接编译,也可以用 ./build.sh --cxx clang++ 切到 Clang 22 + libc++ 对比两套标准库的支持情况。
策略:新代码用 expected + print;需要兼容旧编译器的库代码,可以像 demo 那样用 #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 | ✅ |











