如何保证使用编译时常量初始化堆栈变量

how to guarantee initilization of a stack variable with a compile time constant

在 C++20 中我们现在有 constinitconstexprconsteval.

我现在可以使用 constinit 保证静态变量由 constexprconsteval 函数的结果初始化。好的

我也可以保证堆栈变量是用编译时执行的consteval函数的结果初始化的。

但是我怎样才能强制运行一个constexpr函数在编译时计算结果以在堆栈上初始化一个变量?

// Lets assume that we have a much more complex function so that the compiler will not
// always decide to compile time evaluation automatically 
constexpr int func( int i )
{
    return i+2;
}

int main()
{
     ??? int i = func(8);
     ...
     i = 9;
}

如果我们使用 constexpr 变量是隐式 const 并且 constinit 在这里是不允许的。是否有机会使用 constexpr 函数的编译时评估结果初始化此 var 而无需将其设为 const?我只是想知道为什么 constinit 仅限于静态变量。对我来说意义不大。

我觉得还是用consteval函数比较好,但是如果不能改的话,可以直接用一个临时变量,以后肯定会优化的:

constexpr int func( int i )
{
    return i+2;
}

int main()
{
     constexpr int i1 = func(8);
     auto i2 = i1;
     i2 = 9;
}

虽然你可能不喜欢这种方法,但我认为它没有问题....

你也可以使用这样的东西(基于 StoryTeller ):

template<typename T> constexpr std::remove_const_t<T> const_eval(T&& res) { return res; }

它也支持从方法返回引用。

I am simply wondering why constinit is limited to static variables. For my[sic] it makes not much sense.

常量初始化和动态初始化是仅适用于具有静态存储持续时间的对象的概念。 constinit 说明符仅仅意味着强制我们期望变量将经历前者,而不是后者。它不是优化工具,而是一种规范我们的代码行为方式的方法。没有它,动态初始化可能会悄无声息地发生,正如任何遇到过这种情况的 C++ 程序员都可以告诉您的那样,这也意味着静态初始化顺序可能会失败。

使用 constinit,我们要么得到预期的行为,要么得到诊断。它不适用于自动变量,因为它们不会遇到与静态变量相同的问题。

但是如果你想确保 i 被初始化为 可以 常量计算的东西,那么完成起来并不难。

template<auto result> consteval auto const_eval() { return result; }

int main()
{
     int i = const_eval<func(8)>();
     i = 9;
}

如果 func(8) 不能被常量求值,这是一个硬错误。编译器会将其优化为一个常量值的负载吗?极有可能。编译器擅长这类事情。