std::is_constant_evaluated() 仅在 constexpr 或 consteval 函数体内合法,用于编译期上下文感知分支;其返回值取决于求值时机而非调用位置,且编译期分支内所有代码须满足 constexpr 约束。

std::is_constant_evaluated 必须在 constexpr 函数里用
它在普通函数中调用会直接编译失败,GCC 报 call to non-constexpr function,Clang 也拒绝。这不是运行时判断工具,而是编译期上下文感知开关——只在 constexpr(或 consteval)函数体内才合法。
- 即使函数声明为
constexpr,若调用点不构成常量表达式(比如赋值给int x = f();),std::is_constant_evaluated()仍返回false,但不会报错 - 想验证是否真进了编译期分支?塞进
static_assert或用作数组长度:int arr[my_func(5)];,通不过就说明没走编译期路径 - 不能放在变量初始化器里直接调用:
constexpr bool b = std::is_constant_evaluated();是非法的——它本身不是常量表达式
编译期分支里只能写 constexpr 兼容代码
一旦进入 if (std::is_constant_evaluated()) 分支,所有语句都必须满足常量求值约束:不能 new、不能调用非 constexpr 函数(如 std::strlen、std::printf)、不能读非常量全局变量、不能用未初始化的局部变量地址。
-
std::strlen写在编译期分支里?编译直接挂掉;得挪到else分支 - 查表逻辑可以放进去,但表本身得是
constexpr数组,且索引计算全程可常量折叠 - 递归深度受编译器限制(GCC 默认约 512 层),编译期分支若递归过深,会触发
constexpr evaluation depth exceeded
别指望它自动优化运行时调用
std::is_constant_evaluated() 不是编译器内置优化提示,它不改变调用时机,也不剪枝分支。它只是告诉你“此刻正在被怎么求值”,而不是“请把它变成编译期求值”。
- 传入运行时变量:
int x = get_input(); auto r = safe_sqrt(x);→ 必然走else分支,std::is_constant_evaluated()返回false - 用
consteval强制编译期执行?那std::is_constant_evaluated()就多余了——它恒为true,且无法 fallback - 某些旧版 GCC(
和 if constexpr 的关键区别在哪
if constexpr 是模板编译期分支,条件必须是常量表达式;而 std::is_constant_evaluated() 是运行时函数调用(语法上),但它在编译期求值,返回值取决于**当前调用是否被编译器选为常量求值路径**。
立即学习“C++免费学习笔记(深入)”;
-
if constexpr (std::is_constant_evaluated())是语法错误——std::is_constant_evaluated()不是常量表达式上下文允许的条件 -
if constexpr适合基于类型/值类别做编译期分派;std::is_constant_evaluated()适合同一参数类型下,按调用上下文切换实现 - 两者不互斥:你可以在
if constexpr分支里再嵌套if (std::is_constant_evaluated()),但要清楚外层已限定在 constexpr 函数中
nullptr 检查都要用 constexpr 友好的方式写。


















