【问题标题】:Call to constexpr function accepting an array fails to compile调用接受数组的 constexpr 函数编译失败
【发布时间】:2017-06-27 20:17:21
【问题描述】:

考虑这段代码:

#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

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

【问题讨论】:

    标签: arrays c++14 constexpr non-type template-variables


    【解决方案1】:

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

    theIntArray<xx[0]>;
    

    这只有在xx[0]constexpr 时才有效,但在函数体内xx不是 constexpr

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

    live example.

    【讨论】:

    • TIL 添加对文字类型的 const 引用以模仿用户定义的非类型模板参数。赞成。
    【解决方案2】:

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

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

    你也不能使用函数参数xx[0]作为函数内部的非类型模板参数。 aa[0] 的情况不同,因为它是在函数之外进行评估的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2013-01-26
      • 1970-01-01
      • 2014-04-06
      • 2011-12-08
      • 2019-08-04
      • 1970-01-01
      相关资源
      最近更新 更多