Search code examples
arraysc++14constexprnon-typetemplate-variables

Call to constexpr function accepting an array fails to compile


Consider this code:

#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;
}

In the main() function the first line passes while the second line fails with a strange error message:

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

I am using gcc-7.0.1 and you can find live example here.

Is this according to the standard or it is a bug? What makes the second line fail while the first line passes?


Solution

  • All constexpr functions must be valid with both a constexpr and non-constexpr arguments. Or, in short, the arguments of a constexpr function are not constexpr within the body, but if they are constexpr outside the function body, certian calculations depending on them may be constexpr on return from the function.

    theIntArray<xx[0]>;
    

    this is only valid syntax if xx[0] is constexpr, but within the function body xx is not constexpr.

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

    live example.