编译错误:使用constexpr声明std :: array size

ors*_*onl 0 c++ metaprogramming constexpr c++11 stdarray

我正在学习,constexpr并且据我所知,它constexpr告诉编译器在编译期间计算函数而不是运行时间.我使用以下代码进行测试,但遇到了一个我真的不明白的错误.你能解释一下原因吗?

#include <iostream>
#include <array>
using namespace std;

constexpr int foo(int i)
{
    return i + 5;
}

int main()
{
    int i = 10;
    std::array<int, foo(5)> arr; // OK
    // But...
    std::array<int, foo(i)> arr1; // Error
}
Run Code Online (Sandbox Code Playgroud)

错误是:' i' 的值在常量表达式中不可用.为什么?i事先声明为什么它必须是一个const

max*_*x66 5

为了我的理解,constexpr告诉编译器在编译期间计算函数而不是运行时间.

不完全是:用constexpr编译器可以(不必)计算函数编译时间.编译器会在必要和可能的情况下执行此操作.

的情况下

std::array<int, foo(5)> arr; // OK
Run Code Online (Sandbox Code Playgroud)

这是必要的(因为第二个模板参数std::array必须在编译时知道)并且可能(因为5在编译时是已知的).

但随着

int i = 10;
std::array<int, foo(i)> arr1; // Error
Run Code Online (Sandbox Code Playgroud)

它是必要的(std::array)但不可能(因为它i是一个非常量变量,编译器不能使用i值编译时但只能运行时).

这是必要的,但不可能,所以错误.

但你可以写

int i { 10 };
int j { foo(i) };
Run Code Online (Sandbox Code Playgroud)

因为调用foo(i)编译时间不可能,但是没有必要(因为j可以初始化运行时).因此foo(i)被称为(据称)运行时间.

要编译std::array使用foo(i),您应该定义iconstexpr(或const)

constexpr int i { 10 };
Run Code Online (Sandbox Code Playgroud)

所以编译器可以使用i编译时的值.

为什么?我事先被宣布为什么它必须是一个const?

简短回答:因为C++ 11标准这么说.

答案很长:因为,通过这种方式,构建编译器更简单.如果要使用值编译时,可以将其声明为constexpr,并且编译器会检查它是否永远不会被修改.它(相对)很简单.

否则,如果您可以使用编译时非常量变量的值,编译器应该遵循变量的故事来确定它在constexpr函数中使用时的值.在你的玩具例子很简单,在现实生活中将是一场噩梦.