1

考虑这段代码:

#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,您可以在此处找到实时示例。

这是根据标准还是错误?是什么让第二行失败而第一行通过?

4

2 回答 2

2

所有constexpr函数都必须对 aconstexpr和非constexpr参数都有效。或者,简而言之,函数的参数constexpr不在函数constexpr体中,但如果它们constexpr在函数体之外,则取决于它们的某些计算可能会constexpr从函数返回。

theIntArray<xx[0]>;

这仅是有效的语法 if xx[0]is constexpr,但在函数体xx中 is not constexpr

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

活生生的例子

于 2017-02-09T20:08:17.370 回答
1

不同之处在于 constexpr 函数参数不存在。也就是说,你不能做

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

并且您也不能将函数参数xx[0]用作函数内部的非类型模板参数。它是不同的,aa[0]因为它是在函数之外评估的。

做你想做的唯一方法是使函数参数成为非类型模板参数。为此,请参阅@Yakk 的答案,其中他使用对constexpr数组的 const 引用作为非类型模板参数。

于 2017-02-09T19:37:22.900 回答