使用constexpr数组的元素与const数组的元素实例化模板

Using an element of a constexpr array vs a const array to instantiate a template

本文关键字:数组 元素 实例化 const 使用 constexpr      更新时间:2023-10-16

在回答一个问题时,我遇到了一个我无法解释的问题。

似乎有足够大的差异

constexpr size_t IntArray[2] = {1, 2};

const size_t IntArray[2] = {1, 2};

使得第一个模板的元素可以用来实例化模板,而第二个模板的元素不能。

演示差异的示例程序。

#include <cstddef>
template <size_t N> struct Foo {};
// Works fine
void test1()
{
   constexpr size_t IntArray[2] = {1, 2};
   const size_t i = IntArray[0];
   Foo<i> f;
   (void)f; // Remove unused f warning.
}
// Does not work
void test2()
{
   const size_t IntArray[2] = {1, 2};
   const size_t i = IntArray[0];
   Foo<i> f;
   (void)f; // Remove unused f warning.
}
int main()
{
   return 0;
}

我使用g++ 4.9.2得到以下编译错误:

g++ -std=c++11 -Wall    socc.cc   -o socc
socc.cc: In function ‘void test2()’:
socc.cc:17:8: error: the value of ‘i’ is not usable in a constant expression
    Foo<i> f;
        ^
socc.cc:16:17: note: ‘i’ was not initialized with a constant expression
    const size_t i = IntArray[0];
                 ^
socc.cc:17:9: error: the value of ‘i’ is not usable in a constant expression
    Foo<i> f;
         ^
socc.cc:16:17: note: ‘i’ was not initialized with a constant expression
    const size_t i = IntArray[0];
                 ^
socc.cc:17:9: note: in template argument for type ‘long unsigned int’
    Foo<i> f;
         ^
socc.cc:17:12: error: invalid type in declaration before ‘;’ token
    Foo<i> f;

我的问题是为什么constexpr数组工作,而不是const数组?

constexpr保证该值为编译时值,const只禁止修改该值。

如果const变量是否是编译时值,则很容易标记单个const变量,对于c数组,它需要记住每个索引的信息。

即使我们能做到

const int two = 2;
constexpr int two_bis = two;

下面是不允许的

const size_t IntArray[2] = {1, bar()}; // with non constexpr bar()
constexpr size_t a = intArray[0]; // we might know that is compile time value
constexpr size_t b = intArray[1]; // but this one is clearly not