C ++ constexpr函数总是在编译时评估吗?

时间:2020-10-30 20:26:46

标签: c++ constexpr

如果我想拥有一个与宏具有相同功能的函数,即在编译时计算值,我可以使用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;
}

3 个答案:

答案 0 :(得分:4)

对于C ++ 20,consteval在这里可能是您的朋友:

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

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

答案 1 :(得分:3)

就自己而言,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):

此外,请注意有关宏的问题。宏定义与编译时间评估无关。它更类似于始终内联的函数。

答案 2 :(得分:3)

无法检测是在运行时还是在编译时仅使用C ++本身对某些内容进行了评估,因此as-if rule允许编译器执行所需的操作。

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

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

在优化的构建中,可以期望编译器在编译时尽可能多地执行。 (只要功能主体在当前翻译单元中可见,或者启用了链接时优化,功能甚至都没有constexpr。)