【问题标题】:Compile Error: Use constexpr to declare std::array size编译错误:使用 constexpr 声明 std::array 大小
【发布时间】:2017-12-02 06:37:07
【问题描述】:

我正在学习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
}

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

【问题讨论】:

    标签: c++ c++11 metaprogramming constexpr stdarray


    【解决方案1】:

    据我所知,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) 被称为(据说)运行时。

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

    constexpr int i { 10 };
    

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

    为什么? i 是事先声明的,为什么它必须是一个 const?

    简短回答:因为 C++11 标准是这样说的。

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

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

    【讨论】:

      猜你喜欢
      • 2021-03-28
      • 1970-01-01
      • 2015-02-15
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多