【问题标题】:Compile-time init a NON constant variable编译时初始化一个非常量变量
【发布时间】: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&lt;double&gt;(2, 3, 4);)。

标签: c++ constants constexpr c++20 consteval


【解决方案1】:

你可以使用中间的constexpr变量:

constexpr auto MInit = diag<double>(1,2,3);
auto M = MInit;

你可以用 lambda 包装它:

auto M = [](){ constexpr auto MInit = diag<double>(1,2,3); return MInit; }();

【讨论】:

  • 这看起来是个好主意。虽然,它会和没有中间变量的代码一样快吗?
  • @adel 什么代码没有中间变量?
  • @Yakk-AdamNevraumont 我的意思是:添加中间变量会使代码运行速度变慢吗?
  • @adel 删除中间变量会使初始化在运行时发生,所以不会。如果您想将其与没有中间变量的特定实现进行比较,您将不得不说出是哪一个。因为没有证据表明“完全相同的代码在没有中间变量的情况下表现相同”,我认为这就是您暗示我们应该与之比较的内容。
  • @jarod42 为此,我可能会创建一个全局 constexpr,例如 is_same_v。使用现场的清洁剂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
相关资源
最近更新 更多