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

能否通过返回const对象强制含非const数组的constexpr函数编译期求值?

你的constexpr函数会强制编译期求值吗?

答案是:不会——仅仅将返回对象声明为const并不会强制calculations函数在编译期完成计算。下面来拆解原因和解决方法:

核心误区:const vs constexpr

首先要明确这两个关键字的本质区别:

  • const仅表示变量不可被修改,但它的值完全可以是运行期才确定的;
  • constexpr才是强制要求变量是编译期可计算的常量表达式,这才会触发constexpr函数的编译期求值逻辑。

你的代码里const auto obj2 = ...只是让obj2不可修改,但并没有要求它必须是编译期常量,所以编译器完全可以选择在运行期执行calculations函数。

constexpr函数的求值触发条件

constexpr函数的求值时机完全取决于它的使用上下文,只有当它被用于以下场景时,才会被强制要求在编译期求值:

  • 初始化constexpr变量;
  • 作为模板参数传递;
  • 定义数组的大小;
  • 初始化枚举成员;
  • 作为static_assert的参数等其他需要常量表达式的场景。

回到你的代码,calculations的调用上下文只是初始化一个const变量,不属于上述强制编译期求值的场景。

如何强制编译期求值?

如果你想让calculations必须在编译期完成计算,需要做两个关键修改:

1. 将obj2声明为constexpr

把main里的obj2声明改成:

constexpr auto obj2 = calculations<double, size>(obj1);

这会明确告诉编译器:obj2必须是编译期常量,因此必须在编译期执行calculations函数。

2. 确保函数内部操作符合常量表达式要求

你的代码里还有一个隐藏问题:Array的构造函数不是constexpr,即使你把obj2改成constexpr,编译器也无法在编译期执行Example的构造函数(因为它会调用Array的非constexpr构造函数)。所以需要给Array的构造函数加上constexpr关键字:

template<int Size, typename T>
struct Array{
    T array[Size];
    // 添加constexpr修饰构造函数
    constexpr Array(const T * a){
        for(int i = 0; i < Size; i++){
            array[i] = a[i];
        }
    }
};

做完这两个修改后,calculations就会被强制在编译期求值了。

补充:关于函数内的非const数组

你提到函数内有非const数组D test1[2];,这在C++14及以后的constexpr函数里是允许的——constexpr函数允许修改自动存储期的变量,只要这些操作符合常量表达式的规则。所以这个数组本身不会阻碍编译期求值,真正的关键还是调用上下文是否要求常量表达式。

内容的提问来源于stack exchange,提问作者M.Mac

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:29:49