调用接受数组的 constexpr 函数无法编译

Call to constexpr function accepting an array fails to compile

考虑这段代码:

#include <array>

template < int... Ints >
constexpr std::array<int,sizeof...(Ints)> theIntArray = {Ints...};

template < size_t NN >
constexpr void test(const std::array<int,NN>& xx)
{
    theIntArray<xx[0]>;
}

constexpr std::array<int,2> aa = {10,20};

int main()
{
    theIntArray<aa[0]>; // passes
    test(aa); // FAILS ?!

    return 0;
}

main() 函数中,第一行通过而第二行失败并出现奇怪的错误消息:

error: ‘* & xx’ is not a constant expression
note: in template argument for type ‘int’

我正在使用 gcc-7.0.1,您可以找到实例 here

这是符合标准还是错误?是什么导致第二行失败而第一行通过?

区别在于constexpr函数参数不存在。也就是说,你不能做

constexpr auto fun(int x) {
    constexpr y = x;
    return y;
}

也不能在函数内部使用函数参数 xx[0] 作为 non-type template-parameter。 aa[0] 不同,因为它是在函数外求值的。

做你想做的唯一方法是使函数参数成为 non-type 模板参数。为此,请参阅@Yakk 的答案,他在其中使用 const-reference 到 constexpr 数组作为 non-type 模板参数。

所有 constexpr 函数必须对 constexpr 和非 constexpr 参数都有效。或者,简而言之,constexpr 函数的参数不在主体内 constexpr,但如果它们在函数主体外 constexpr,则依赖于它们的 certian 计算可能是 constexpr 在 return 上来自函数。

theIntArray<xx[0]>;

只有当 xx[0]constexpr 时,这才是有效的语法,但在函数体中 xxnot constexpr .

template < size_t NN, std::array<int,NN> const& xx >
constexpr void test()
{
  theIntArray<xx[0]>;
}

live example.