【发布时间】:2021-04-22 18:30:50
【问题描述】:
问题: 如何在编译时使用函数初始化非常量变量,同时仍然启用对所述函数的运行时调用?
详情:我使用的是C++20,我有以下代码:
template<typename T>
constexpr auto diag(auto&&.. vals) {...}
// ...
constexpr auto M = diag<double>(1,2,3);
A 预期,上面的代码编译,diag 在编译时执行,M 是常量。 如果我将呼叫线路更改为
auto M = diag<double>(1,2,3);
代码再次编译,但这次是在运行时执行 diag,并且 M 不是常量。
我想结合以上两个:让 diag 在编译时执行,但保持 M 可变;基本上是在编译时用一些复杂的东西初始化一个非常量变量,比如 diag 的返回值。
方法:我把代码改成
template<typename T>
consteval auto diag(auto&&.. vals) {...}
// ...
auto M = diag<double>(1,2,3);
这一次,M 是非常量的,而 diag 是在编译时执行的,所以有效地达到了我的目标。我的问题是:consteval 必须在编译时执行,所以如果我想在运行时代码的其他地方使用 diag,我将不得不编写另一个函数。
这就引出了问题: 如何在编译时使用函数初始化非常量变量,同时仍然启用对所述函数的运行时调用?
注意: 在上面的示例代码中,diag 创建了一个具有给定条目的对角矩阵。我希望代码相当于
Matrix<double, 3, 3> M = { {1.0,0.0,0.0}, {0.0,2.0,0.0}, {0.0,0.0,3.0}};
这里,M 不是一个常数,而是从一个常数、编译时确定的对角矩阵分配的。
【问题讨论】:
-
从
M中删除constexpr时,您如何确定该函数在运行时执行?这听起来很奇怪,因为分配给的变量不应该影响函数是否可以在编译时评估。constexpr函数可以两者兼得,所以它应该是你想要的。 -
由于你使用的是c++20,你见过新的constinit说明符吗?
-
@super 我使用了std::is_constant_evaluated。是的,我也觉得很奇怪。首先我认为这取决于我是否有 constexpr 构造函数,但它似乎没有做出改变。
-
如果您提供一个证明这一点的minimal reproducible example,这将使您的问题更容易回答。
-
@super 使用 constinit 我得到以下错误(gcc):
constinit’ can only be applied to a variable with static or thread storage duration(我在 mí 代码中有constinit auto M = diag<double>(2, 3, 4);)。
标签: c++ constants constexpr c++20 consteval