【问题标题】:C++ constexpr function always evaluated at compile time?C++ constexpr 函数总是在编译时评估?
【发布时间】:2021-02-13 07:49:46
【问题描述】:

如果我想要一个行为与宏相同的函数,即在编译时计算值,我可以使用 constexpr 函数吗?

例如,我是否可以用 foo 函数替换 Foo 宏,并且在以下所有情况下仍然有编译时评估结果:

#define FOO(x) (x + 2)

constexpr int foo(int x) {
    return x + 2;
}

void doSomething(int a) { ... }

int main() {
    int res1 = foo(3);
    doSomething(foo(4));
    const int res2 = foo(5);
    return 0;
}

【问题讨论】:

标签: c++ constexpr


【解决方案1】:

使用 C++20,consteval 可能是您的朋友:

consteval int foo(int x) {
    return x + 2;
}

int main() {
    constexpr int r = foo(2);
}

【讨论】:

    【解决方案2】:

    constexpr 函数本身不需要在编译时进行评估。但是,您可以通过将返回值分配给 constexpr 变量来强制对它们进行评估:

    doSomething(foo(4)); // foo(4) not guaranteed to be evaluated at compile time
    constexpr auto result = foo(4); // foo(4) _is_ guaranteed to be evaluated at compile time
    doSomething(result):
    

    另外,关于您关于宏的问题的说明。宏定义与编译时评估无关。它更类似于始终内联函数。

    【讨论】:

    • 其实第一个是保证在运行时被求值的。
    • @cigien 是否以某种方式免于 as-if 规则?
    • @HolyBlackCat 不,程序必须仍然表现如同调用被不断评估。我会试着写一个答案。
    • @cigien - 你是指doSomething(foo(4)) 中的foo() 调用吗?你确定吗?
    【解决方案3】:

    仅使用 C++ 本身无法检测是否在运行时或编译时对某些内容进行了评估,因此as-if rule 允许编译器为所欲为。

    没有什么能阻止编译器在运行时在你的宏中执行加法,也没有什么能阻止它在编译时计算即使是非constexpr 函数(只要它不执行任何 IO 等)。这完全取决于优化设置和编译器的健全性。

    通常,在未优化的构建中,constexpr 函数在运行时执行,除非在需要编译时常量的上下文中使用返回值。这包括从中初始化一个constexpr 变量,并且您的const int res2 隐式变为constexpr,因为它的初始化程序是constexpr,所以foo(5) 应该在编译时调用。

    在优化的构建中,您可以期望编译器在编译时做尽可能多的事情。 (函数甚至没有constexpr,只要函数体在当前翻译单元中可见,或者启用了链接时优化。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 2020-10-01
      • 2014-04-06
      • 2021-09-04
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多