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

时间:2017-06-28 18:41:24

标签: c++ c++11 metaprogramming constexpr 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
}

错误是:&#39; i&#39;不能用于常量表达式。为什么?事先声明i为什么它必须是const

1 个答案:

答案 0 :(得分:5)

  

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

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

如果是

std::array<int, foo(5)> arr; // OK

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

但是

int i = 10;
std::array<int, foo(i)> arr1; // Error

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

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

但你可以写

int i { 10 };
int j { foo(i) };

因为它不可能调用foo(i)编译时间但是没有必要(因为j可以在运行时初始化)。所以foo(i)被称为(假设)运行时间。

要使用std::array汇编foo(i),您应将i定义为constexpr(或const

constexpr int i { 10 };

因此编译器可以使用i编译时的值。

  

为什么呢?我事先声明为什么它必须是一个const?

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

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

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