@@ -1367,10 +1367,13 @@ constexpr int factorial_11(int n) {
13671367}
13681368
13691369// C++14:可以用循环(更直观、更高效)
1370- constexpr int factorial_14(int n) {
1371- int result = 1;
1372- for (int i = 2; i <= n; ++i)
1373- result * = i;
1370+ // 注意返回类型用 unsigned long long:阶乘增长极快,13! = 6227020800 已超过
1371+ // INT_MAX(2147483647),用 int 会发生有符号整数溢出(未定义行为,UB)。
1372+ // 无符号类型溢出是良定义的回绕(取模 2^64),20! 仍可精确表示。
1373+ constexpr unsigned long long factorial_14(unsigned long long n) {
1374+ unsigned long long result = 1;
1375+ for (unsigned long long i = 2; i <= n; ++i)
1376+ result * = static_cast<unsigned long long >(i);
13741377 return result;
13751378}
13761379
@@ -1423,7 +1426,7 @@ C++20 和 C++23 极大地扩展了 `constexpr` 的能力边界,使得越来越
14231426| C++20 | `constexpr` 虚函数、析构函数、`new/delete`(瞬态) | 编译期多态、编译期动态数据结构 |
14241427| C++20 | `constexpr std::vector`、`constexpr std::string` | 编译期容器操作 |
14251428| C++23 | `constexpr std::unique_ptr`(P2273R3) | 编译期所有权管理 |
1426- | C++23 | `constexpr <cmath>`(P0533R9)——`std::sin `、`std::cos` 等 | 编译期三角函数计算 |
1429+ | C++23 | `constexpr <cmath>` 基本函数 (P0533R9)——`std::abs `、`std::ceil`、`std::floor`、`std::round` 等基本运算;`sin`/` cos` 等超越函数另见 P1383,目标 C++26 | 编译期基本数学运算 |
14271430| C++23 | `constexpr <bitset>` | 编译期位操作 |
14281431
14291432**C++20 的 `constexpr new/delete`** 是一个革命性的变化。它允许在 `constexpr` 函数中使用 `new` 和 `delete`——但有一个关键限制:**分配必须是瞬态的**(transient allocation),即在编译期求值结束前必须被释放。这意味着 `constexpr std::vector` 可以在编译期增长和收缩,但不能把堆分配的结果"带出"编译期留到运行时。
@@ -1443,7 +1446,7 @@ constexpr auto computeSquares() {
14431446static_assert(computeSquares() == 285); // 0+1+4+9+16+25+36+49+64+81
14441447```
14451448
1446- ** 在机器人代码中的应用前景** :随着 ` constexpr std:: sin/ cos` 在 C++23 中成为标准,之前需要用 Taylor 展开近似实现的编译期三角函数查找表,现在可以直接用标准库函数,精度和行为与运行时版本完全一致 。
1449+ ** 在机器人代码中的应用前景** :上表中的 P0533R9 只覆盖了 ` abs ` 、 ` ceil ` 、 ` floor ` 、 ` round ` 等基本算术函数, ` sin ` / ` cos ` 等超越函数的 ` constexpr ` 化由另一份提案 P1383 负责,目标标准为 C++26。在此之前,若需要编译期三角函数查找表,仍需使用 Taylor 展开等手工近似实现——下面的代码示例就展示了这种过渡方案 。
14471450
14481451> ** 反事实推理** :如果 C++11 一开始就有 ` constexpr std::vector ` ,很多模板元编程中用递归类型列表实现的"编译期数组"就不需要了。` std::tuple ` 的大量使用场景也可以被更直观的 ` constexpr std::vector ` 替代——代码从类型体操变成普通循环,可读性大幅提升。
14491452
@@ -1494,10 +1497,9 @@ constexpr double kMaxVelocity = 1.0; // m/s
14941497constexpr double kControlFreq = 1000.0 ; // Hz
14951498constexpr double kDt = 1.0 / kControlFreq ; // 编译期计算时间步长
14961499
1497- // constexpr 查找表——仅用于演示 constexpr 语法
1498- // C++23 起 std::sin 已是 constexpr(P0533R9),实际项目直接用 std::sin 即可
1499- // 以下 5 阶 Taylor 展开仅在 |x| < 1 rad(约 57°)时精度可接受,
1500- // 超出此范围误差极大(sin(180°) ≈ 0.52 而非 0)——不可用于实际计算
1500+ // constexpr 查找表——用 Taylor 展开近似 sin,演示 C++23 尚无 constexpr std::sin 时的过渡写法
1501+ // 5 阶展开在 |x| < 1 rad(约 57°)时精度可接受;超出此范围误差极大(sin(180°) ≈ 0.52 而非 0)
1502+ // C++26 P1383 落地后可直接替换为 constexpr std::sin
15011503constexpr auto makeSinTableDemo () {
15021504 std::array<double, 360> table{};
15031505 for (int i = 0; i < 360; ++i) {
0 commit comments