constexpr - "在编译期计算数值" 究竟是什么意思?

3
#include <array>

int value1(int param) {
    return param * 2;
}

constexpr int value2(int param) {
    return param * 2;
}

int main() {
    const int i = 10;

    std::array<int, value1(i)> starr1 = {}; // 1
    std::array<int, value2(i)> starr2 = {}; // 2

    return 0;
}

2 是可以的,但 1 会导致编译错误,因为 std::array 必须创建静态大小数组。 value2() 使用了 constexpr 关键字,返回一个编译时常量值。

那么,编译器是如何推断出 value2(i) 是编译时常量呢?它在编译时调用函数 value2() 吗?

const int value1(int param) {
    return param * 2;
}

int main() {
    const int i = 10;
    std::array<int, value1(i)> starr1 = {}; // 3

    return 0;
}

>>> error: call to non-constexpr functionconst int value1(int)’

此外,3仍然会产生编译错误。即使将const关键字应用于函数value1()value1(i)是否不是编译时常量?
1个回答

7
那么,编译器如何推断value2(i)是编译时常量呢?
它并不会自动推断。你需要在注释中用constexpr显式地标明。对于未使用constexpr标记的函数,它可能会自动推断,但这仍然无法使你在编译时表达式中使用它们的结果,而只能作为一种优化策略。
它在编译时调用函数value2()吗?
从某种意义上来说,是的。更准确地说,编译器没有为执行构建期间的代码而编译该函数。重要的是,它能够在整个程序构建和运行之前确定其结果,并且可以在生成代码时使用该结果,例如确定array的大小。
即使函数value1()应用了const关键字,value1(i)也不能成为编译时常量吗?
不能。const只适用于返回类型(在这种情况下,它实际上是无用的),而不适用于编译时的求值可能性。

3
顺便提一下,在 C++20 中,加入了 consteval,这使得情况更加复杂,但我认为这超出了本问题的讨论范围。 - Bartek Banachewicz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接