【问题标题】:Can you have constexpr rvalues? [duplicate]你能有 constexpr 右值吗? [复制]
【发布时间】:2020-03-09 12:01:04
【问题描述】:

你能有 constexpr 右值吗,例如使用几个 constexpr 函数的结果初始化变量时?

即无论编译器设置如何,我可以保证在编译时计算右值吗?


constexpr int getvalue1()
{
    return 42;
}

constexpr int getvalue2()
{
    return 24;
}

int main()
{


    // I want to initialize val with a value known at compile time
    constexpr int ceval  = getvalue1() + getvalue2();
    int val = ceval;

    // why can't I just do:
    // 
    // int val = constexpr getvalue1() + constexpr getvalue2();

}

https://godbolt.org/z/KcK23k

【问题讨论】:

  • 为什么你认为你不能做你认为你不能做的事情?你可以做到的。
  • @Cubic int val = constexpr getvalue1() + constexpr getvalue2(); 此行无法编译:错误:预期表达式。
  • 是的,getvalue1() 返回一个 constexpr 右值。它可能会或可能不会在编译时实际计算。在发布版本中,它可能会在编译时计算。像您所做的那样,使用 constexpr 变量应该强制在编译时计算它,而不管编译器设置如何。在 C++20 中,您还可以使用 consteval。
  • @iwans 为什么你认为它应该编译?你不能只是想出一些语法并期望它起作用。
  • @HolyBlackCat 我不认为它应该编译,我问我是否可以保证无论编译器设置如何,都会在编译时计算 r 值。

标签: c++ c++17 constexpr


【解决方案1】:

只需使用:

int val = getvalue1() + getvalue2();

优化器会处理它。如果您禁用优化器,那么是的,编译器将调用这些函数,否则您将无法设置断点并单步执行。

即使你使用 C++20 的 consteval 说明符,它要求函数产生一个常量表达式,如果你禁用优化器,编译器仍然会发出调用:

consteval int getvalue1()
{ return 42; }

consteval int getvalue2()
{ return 24; }

// ...
int val = getvalue1() + getvalue2();

长话短说:只需使用优化器。如果您像通过中间 constexpr 变量那样强制解决问题,那么当您最终不得不实际调试 constexpr 或 consteval 函数时,您所做的只是让调试变得更加困难。

【讨论】:

  • 查看生成的程序集时,会创建两个函数调用。 godbolt.org/z/dyRc_2 优化关闭
  • @iwans 那是因为您没有启用任何优化。即使使用-O1,您也无需调用即可获得编译时值。
  • @iwans constexpr 并不意味着“不要在运行时进行函数调用”。那不是它的用途。所有编译器通常的“嗯,我应该内联还是不应该内联”规则都适用。
  • @iwans [ProTip] 总是在您想查看程序集时打开优化器。如果不启用优化,很多时候你会得到你写的字面意思,这通常不是最佳的。
  • @iwans constexpr 仅表示函数调用或变量的值可以在编译时计算,而不是必须。这样做本身就是一种编译器优化形式(一个相当基本的优化,也是constexpr 存在的主要原因),根据标准,它不是可以强制执行或保证的。跨度>
【解决方案2】:

对于 C++11 功能,您无法保证这一点,尽管如果您不关闭优化,大多数编译器会针对这种简单的情况执行此操作。

C++20 仅出于此目的添加了 constinit 关键字,但这仅适用于静态或线程局部变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-08
    • 2017-01-01
    • 2016-11-30
    • 2018-07-29
    • 2018-10-06
    • 2011-08-04
    • 2020-12-23
    • 2015-12-09
    相关资源
    最近更新 更多