std::is_constant_evaluated()用于在constexpr函数中区分编译期与运行时分支:编译期分支必须仅含constexpr兼容操作(如字面量计算、constexpr函数),禁用std::sqrt等非constexpr标准函数;运行时分支可自由调用标准库并处理异常;错误使用会导致编译失败,正确使用可实现零开销编译期常量生成。

它不能自动加速运行时代码,但能让你在同一个 constexpr 函数里安全切出编译期硬编码路径和运行时通用路径——用错一行,编译直接失败;用对了,单位向量、旋转矩阵常量全在编译期生成,零开销。
编译期归一化必须避开 std::sqrt
向量归一化(v / ||v||)在编译期已知长度时,应完全折叠为比例系数;但 std::sqrt 在 C++20 及之前不是 constexpr 函数,直接调用会触发硬编译错误。
- 编译期分支只能用:
constexpr版本的牛顿迭代、手工展开的平方根近似(如对小整数查表)、或 C++23 的std::sqrt(需-std=c++23) - 运行时分支可自由调用
std::sqrt、std::hypot,并加入 NaN 检测和异常处理 - 中间变量如长度平方必须声明为
constexpr double len2 = x*x + y*y + z*z;,否则编译器无法保证其为常量 - 常见错误:在
if constexpr (std::is_constant_evaluated())分支里写return v / std::sqrt(len2);→ GCC/Clang 都报 “call to non-constexpr function”
齐次变换矩阵的静态生成要禁用 std::sin/std::cos
绕固定轴旋转 90°、180° 等特殊角度的矩阵,在编译期应直接返回字面量数组;但 std::sin 和 std::cos 在绝大多数标准下都不是 constexpr,混入编译期分支会导致整个函数失效。
- 编译期分支只允许对字面量角度做
constexpr if或switch判断,例如:if constexpr (angle == 1.5707963267948966) { return std::array{...}; } - 运行时分支才调用
std::sin(angle)、std::cos(angle)并填充std::array - 禁止在编译期分支中构造
std::vector缓存常见角度值——即使你没用它,只要代码存在,就违反 constexpr 约束 - 典型误用:
constexpr auto s = std::sin(angle);放在 true 分支里 → 编译失败,且错误位置指向这行,而非if判断本身
为什么 std::is_constant_evaluated() 在 int x = f(5); 里永远返回 false
它不看参数是不是字面量,只看“这次调用是否被上下文明确要求常量表达式”。普通变量初始化不强制常量求值,所以分支永远进不去编译期逻辑。
- 真正有效的调用点只有:
static_assert(f(5) == 42);、constexpr int y = f(5);、int arr[f(5)];、模板非类型参数推导(如template中的struct X {}; X) -
const int x = f(5);不行 —— C++ 标准不要求const初始化走常量求值 -
constinit int x = f(5);在部分 GCC 版本中可能触发 true,但 Clang 更保守;跨平台项目应以 Clang 行为为准,别依赖它 - 验证是否真进了编译期:唯一可靠方式是用
static_assert包裹调用,通过即说明成功
分支合法性检查发生在编译期,且是硬约束
编译器不会运行时判断该走哪条路,而是在常量求值阶段严格检查编译期分支里的每一行是否合法。哪怕你只打算在运行时使用这个函数,只要它被用于某个 static_assert,整个编译期分支就必须 100% 符合 constexpr 要求。
- 编译期分支里出现
new、std::cout、对非常量全局变量取地址、throw、dynamic_cast→ 直接编译失败 - 运行时分支可以任意写,但它不能“污染”编译期分支——比如在 else 里定义
std::string s,再试图把它传给一个编译期分支中的辅助函数 - 推荐做法:把两套逻辑拆成独立函数,主函数只做跳转,例如
constexpr_f_impl()和runtime_f_impl(),降低误触风险 - 最容易被忽略的点:分支内循环展开深度受编译器限制(GCC 默认约 512 层),递归过深也会导致常量求值失败,而非运行时崩溃
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











