You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用is_constant_evaluated统一constexpr函数行为遇编译错误咨询

std::is_constant_evaluated 导致的常量表达式编译错误分析

问题场景

使用GCC12.2编译器并开启-std=c++20编译选项编写代码,尝试通过std::is_constant_evaluated统一constexpr函数的行为,但调用LOGMSG(str1)时出现编译错误:

error: the value of ‘str1’ is not usable in a constant expression
      constexpr auto numArgs = count(FMT); 

相关代码

#include <memory>
#include <iostream>
#include <string.h>


template<size_t arrSize>
void print()
{
    std::cout << "Number of format characters: " << arrSize << "\n";
}

constexpr size_t countFormat(const char* format)
{
    if(format[0] == '\0')
       return 0;
    return (format[0] == '%' ? 1u : 0u) + countFormat(format + 1);
}

constexpr size_t count(const char* format)
{
    return std::is_constant_evaluated() ? countFormat( format ) : 0;
}

#define LOGMSG(FMT) {  
    constexpr auto numArgs = count(FMT); 
    print<numArgs>(); 
}

int main()
{
    const auto str1 = "Test %d %s";
    constexpr auto str2 = "Test %d %s";
    LOGMSG(str1);
    LOGMSG(str2);
    LOGMSG("Test %d %s");
    return 0;
}

错误原因

核心矛盾:const与constexpr变量的本质区别

str1是**const修饰的自动存储期变量**,而非constexpr变量:

  • 虽然str1的值是字符串字面量,但它存储在栈上(自动存储期),其地址不属于常量表达式范畴。
  • 当LOGMSG(str1)展开后,constexpr auto numArgs = count(str1);要求count(str1)必须是常量表达式(因为numArgs是constexpr变量),此时整个count函数的调用处于常量求值上下文,std::is_constant_evaluated()会返回true,进而执行countFormat(str1)。
  • countFormat需要在常量求值中访问format指向的内容,但str1的地址不是常量表达式,无法在常量求值过程中被合法引用,因此触发编译错误。

对比成功案例的逻辑

  • str2是constexpr变量:其地址属于常量表达式,能在常量求值中被countFormat正常访问。
  • 直接传入字符串字面量:字符串字面量本身就是常量表达式,自然满足常量求值的要求。

关于std::is_constant_evaluated的误区

std::is_constant_evaluated()仅用于判断当前是否处于常量求值上下文,无法将非常量表达式的参数“转换”为常量表达式。只要count被用于初始化constexpr变量,就必须保证整个调用链都符合常量表达式的要求,而str1不满足这一前提。

内容的提问来源于stack exchange,提问作者bramasub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:06:49